Linux-libre 5.4.48-gnu
[librecmc/linux-libre.git] / drivers / staging / greybus / tools / loopback_test.c
1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3  * Loopback test application
4  *
5  * Copyright 2015 Google Inc.
6  * Copyright 2015 Linaro Ltd.
7  */
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <stdlib.h>
13 #include <stdint.h>
14 #include <poll.h>
15 #include <sys/types.h>
16 #include <time.h>
17 #include <unistd.h>
18 #include <dirent.h>
19 #include <signal.h>
20
21 #define MAX_NUM_DEVICES 10
22 #define MAX_SYSFS_PREFIX 0x80
23 #define MAX_SYSFS_PATH  0x200
24 #define CSV_MAX_LINE    0x1000
25 #define SYSFS_MAX_INT   0x20
26 #define MAX_STR_LEN     255
27 #define DEFAULT_ASYNC_TIMEOUT 200000
28
29 struct dict {
30         char *name;
31         int type;
32 };
33
34 static struct dict dict[] = {
35         {"ping", 2},
36         {"transfer", 3},
37         {"sink", 4},
38         {NULL,}         /* list termination */
39 };
40
41 struct loopback_results {
42         float latency_avg;
43         uint32_t latency_max;
44         uint32_t latency_min;
45         uint32_t latency_jitter;
46
47         float request_avg;
48         uint32_t request_max;
49         uint32_t request_min;
50         uint32_t request_jitter;
51
52         float throughput_avg;
53         uint32_t throughput_max;
54         uint32_t throughput_min;
55         uint32_t throughput_jitter;
56
57         float apbridge_unipro_latency_avg;
58         uint32_t apbridge_unipro_latency_max;
59         uint32_t apbridge_unipro_latency_min;
60         uint32_t apbridge_unipro_latency_jitter;
61
62         float gbphy_firmware_latency_avg;
63         uint32_t gbphy_firmware_latency_max;
64         uint32_t gbphy_firmware_latency_min;
65         uint32_t gbphy_firmware_latency_jitter;
66
67         uint32_t error;
68 };
69
70 struct loopback_device {
71         char name[MAX_STR_LEN];
72         char sysfs_entry[MAX_SYSFS_PATH];
73         char debugfs_entry[MAX_SYSFS_PATH];
74         struct loopback_results results;
75 };
76
77 struct loopback_test {
78         int verbose;
79         int debug;
80         int raw_data_dump;
81         int porcelain;
82         int mask;
83         int size;
84         int iteration_max;
85         int aggregate_output;
86         int test_id;
87         int device_count;
88         int list_devices;
89         int use_async;
90         int async_timeout;
91         int async_outstanding_operations;
92         int us_wait;
93         int file_output;
94         int stop_all;
95         int poll_count;
96         char test_name[MAX_STR_LEN];
97         char sysfs_prefix[MAX_SYSFS_PREFIX];
98         char debugfs_prefix[MAX_SYSFS_PREFIX];
99         struct timespec poll_timeout;
100         struct loopback_device devices[MAX_NUM_DEVICES];
101         struct loopback_results aggregate_results;
102         struct pollfd fds[MAX_NUM_DEVICES];
103 };
104
105 struct loopback_test t;
106
107 /* Helper macros to calculate the aggregate results for all devices */
108 static inline int device_enabled(struct loopback_test *t, int dev_idx);
109
110 #define GET_MAX(field)                                                  \
111 static int get_##field##_aggregate(struct loopback_test *t)             \
112 {                                                                       \
113         uint32_t max = 0;                                               \
114         int i;                                                          \
115         for (i = 0; i < t->device_count; i++) {                         \
116                 if (!device_enabled(t, i))                              \
117                         continue;                                       \
118                 if (t->devices[i].results.field > max)                  \
119                         max = t->devices[i].results.field;              \
120         }                                                               \
121         return max;                                                     \
122 }                                                                       \
123
124 #define GET_MIN(field)                                                  \
125 static int get_##field##_aggregate(struct loopback_test *t)             \
126 {                                                                       \
127         uint32_t min = ~0;                                              \
128         int i;                                                          \
129         for (i = 0; i < t->device_count; i++) {                         \
130                 if (!device_enabled(t, i))                              \
131                         continue;                                       \
132                 if (t->devices[i].results.field < min)                  \
133                         min = t->devices[i].results.field;              \
134         }                                                               \
135         return min;                                                     \
136 }                                                                       \
137
138 #define GET_AVG(field)                                                  \
139 static int get_##field##_aggregate(struct loopback_test *t)             \
140 {                                                                       \
141         uint32_t val = 0;                                               \
142         uint32_t count = 0;                                             \
143         int i;                                                          \
144         for (i = 0; i < t->device_count; i++) {                         \
145                 if (!device_enabled(t, i))                              \
146                         continue;                                       \
147                 count++;                                                \
148                 val += t->devices[i].results.field;                     \
149         }                                                               \
150         if (count)                                                      \
151                 val /= count;                                           \
152         return val;                                                     \
153 }                                                                       \
154
155 GET_MAX(throughput_max);
156 GET_MAX(request_max);
157 GET_MAX(latency_max);
158 GET_MAX(apbridge_unipro_latency_max);
159 GET_MAX(gbphy_firmware_latency_max);
160 GET_MIN(throughput_min);
161 GET_MIN(request_min);
162 GET_MIN(latency_min);
163 GET_MIN(apbridge_unipro_latency_min);
164 GET_MIN(gbphy_firmware_latency_min);
165 GET_AVG(throughput_avg);
166 GET_AVG(request_avg);
167 GET_AVG(latency_avg);
168 GET_AVG(apbridge_unipro_latency_avg);
169 GET_AVG(gbphy_firmware_latency_avg);
170
171 void abort(void)
172 {
173         _exit(1);
174 }
175
176 void usage(void)
177 {
178         fprintf(stderr, "Usage: loopback_test TEST [SIZE] ITERATIONS [SYSPATH] [DBGPATH]\n\n"
179         "  Run TEST for a number of ITERATIONS with operation data SIZE bytes\n"
180         "  TEST may be \'ping\' \'transfer\' or \'sink\'\n"
181         "  SIZE indicates the size of transfer <= greybus max payload bytes\n"
182         "  ITERATIONS indicates the number of times to execute TEST at SIZE bytes\n"
183         "             Note if ITERATIONS is set to zero then this utility will\n"
184         "             initiate an infinite (non terminating) test and exit\n"
185         "             without logging any metrics data\n"
186         "  SYSPATH indicates the sysfs path for the loopback greybus entries e.g.\n"
187         "          /sys/bus/greybus/devices\n"
188         "  DBGPATH indicates the debugfs path for the loopback greybus entries e.g.\n"
189         "          /sys/kernel/debug/gb_loopback/\n"
190         " Mandatory arguments\n"
191         "   -t     must be one of the test names - sink, transfer or ping\n"
192         "   -i     iteration count - the number of iterations to run the test over\n"
193         " Optional arguments\n"
194         "   -S     sysfs location - location for greybus 'endo' entries default /sys/bus/greybus/devices/\n"
195         "   -D     debugfs location - location for loopback debugfs entries default /sys/kernel/debug/gb_loopback/\n"
196         "   -s     size of data packet to send during test - defaults to zero\n"
197         "   -m     mask - a bit mask of connections to include example: -m 8 = 4th connection -m 9 = 1st and 4th connection etc\n"
198         "                 default is zero which means broadcast to all connections\n"
199         "   -v     verbose output\n"
200         "   -d     debug output\n"
201         "   -r     raw data output - when specified the full list of latency values are included in the output CSV\n"
202         "   -p     porcelain - when specified printout is in a user-friendly non-CSV format. This option suppresses writing to CSV file\n"
203         "   -a     aggregate - show aggregation of all enabled devices\n"
204         "   -l     list found loopback devices and exit\n"
205         "   -x     Async - Enable async transfers\n"
206         "   -o     Async Timeout - Timeout in uSec for async operations\n"
207         "   -O     Poll loop time out in seconds(max time a test is expected to last, default: 30sec)\n"
208         "   -c     Max number of outstanding operations for async operations\n"
209         "   -w     Wait in uSec between operations\n"
210         "   -z     Enable output to a CSV file (incompatible with -p)\n"
211         "   -f     When starting new loopback test, stop currently running tests on all devices\n"
212         "Examples:\n"
213         "  Send 10000 transfers with a packet size of 128 bytes to all active connections\n"
214         "  loopback_test -t transfer -s 128 -i 10000 -S /sys/bus/greybus/devices/ -D /sys/kernel/debug/gb_loopback/\n"
215         "  loopback_test -t transfer -s 128 -i 10000 -m 0\n"
216         "  Send 10000 transfers with a packet size of 128 bytes to connection 1 and 4\n"
217         "  loopback_test -t transfer -s 128 -i 10000 -m 9\n"
218         "  loopback_test -t ping -s 0 128 -i -S /sys/bus/greybus/devices/ -D /sys/kernel/debug/gb_loopback/\n"
219         "  loopback_test -t sink -s 2030 -i 32768 -S /sys/bus/greybus/devices/ -D /sys/kernel/debug/gb_loopback/\n");
220         abort();
221 }
222
223 static inline int device_enabled(struct loopback_test *t, int dev_idx)
224 {
225         if (!t->mask || (t->mask & (1 << dev_idx)))
226                 return 1;
227
228         return 0;
229 }
230
231 static void show_loopback_devices(struct loopback_test *t)
232 {
233         int i;
234
235         if (t->device_count == 0) {
236                 printf("No loopback devices.\n");
237                 return;
238         }
239
240         for (i = 0; i < t->device_count; i++)
241                 printf("device[%d] = %s\n", i, t->devices[i].name);
242
243 }
244
245 int open_sysfs(const char *sys_pfx, const char *node, int flags)
246 {
247         int fd;
248         char path[MAX_SYSFS_PATH];
249
250         snprintf(path, sizeof(path), "%s%s", sys_pfx, node);
251         fd = open(path, flags);
252         if (fd < 0) {
253                 fprintf(stderr, "unable to open %s\n", path);
254                 abort();
255         }
256         return fd;
257 }
258
259 int read_sysfs_int_fd(int fd, const char *sys_pfx, const char *node)
260 {
261         char buf[SYSFS_MAX_INT];
262
263         if (read(fd, buf, sizeof(buf)) < 0) {
264                 fprintf(stderr, "unable to read from %s%s %s\n", sys_pfx, node,
265                         strerror(errno));
266                 close(fd);
267                 abort();
268         }
269         return atoi(buf);
270 }
271
272 float read_sysfs_float_fd(int fd, const char *sys_pfx, const char *node)
273 {
274         char buf[SYSFS_MAX_INT];
275
276         if (read(fd, buf, sizeof(buf)) < 0) {
277
278                 fprintf(stderr, "unable to read from %s%s %s\n", sys_pfx, node,
279                         strerror(errno));
280                 close(fd);
281                 abort();
282         }
283         return atof(buf);
284 }
285
286 int read_sysfs_int(const char *sys_pfx, const char *node)
287 {
288         int fd, val;
289
290         fd = open_sysfs(sys_pfx, node, O_RDONLY);
291         val = read_sysfs_int_fd(fd, sys_pfx, node);
292         close(fd);
293         return val;
294 }
295
296 float read_sysfs_float(const char *sys_pfx, const char *node)
297 {
298         int fd;
299         float val;
300
301         fd = open_sysfs(sys_pfx, node, O_RDONLY);
302         val = read_sysfs_float_fd(fd, sys_pfx, node);
303         close(fd);
304         return val;
305 }
306
307 void write_sysfs_val(const char *sys_pfx, const char *node, int val)
308 {
309         int fd, len;
310         char buf[SYSFS_MAX_INT];
311
312         fd = open_sysfs(sys_pfx, node, O_RDWR);
313         len = snprintf(buf, sizeof(buf), "%d", val);
314         if (write(fd, buf, len) < 0) {
315                 fprintf(stderr, "unable to write to %s%s %s\n", sys_pfx, node,
316                         strerror(errno));
317                 close(fd);
318                 abort();
319         }
320         close(fd);
321 }
322
323 static int get_results(struct loopback_test *t)
324 {
325         struct loopback_device *d;
326         struct loopback_results *r;
327         int i;
328
329         for (i = 0; i < t->device_count; i++) {
330                 if (!device_enabled(t, i))
331                         continue;
332
333                 d = &t->devices[i];
334                 r = &d->results;
335
336                 r->error = read_sysfs_int(d->sysfs_entry, "error");
337                 r->request_min = read_sysfs_int(d->sysfs_entry, "requests_per_second_min");
338                 r->request_max = read_sysfs_int(d->sysfs_entry, "requests_per_second_max");
339                 r->request_avg = read_sysfs_float(d->sysfs_entry, "requests_per_second_avg");
340
341                 r->latency_min = read_sysfs_int(d->sysfs_entry, "latency_min");
342                 r->latency_max = read_sysfs_int(d->sysfs_entry, "latency_max");
343                 r->latency_avg = read_sysfs_float(d->sysfs_entry, "latency_avg");
344
345                 r->throughput_min = read_sysfs_int(d->sysfs_entry, "throughput_min");
346                 r->throughput_max = read_sysfs_int(d->sysfs_entry, "throughput_max");
347                 r->throughput_avg = read_sysfs_float(d->sysfs_entry, "throughput_avg");
348
349                 r->apbridge_unipro_latency_min =
350                         read_sysfs_int(d->sysfs_entry, "apbridge_unipro_latency_min");
351                 r->apbridge_unipro_latency_max =
352                         read_sysfs_int(d->sysfs_entry, "apbridge_unipro_latency_max");
353                 r->apbridge_unipro_latency_avg =
354                         read_sysfs_float(d->sysfs_entry, "apbridge_unipro_latency_avg");
355
356                 r->gbphy_firmware_latency_min =
357                         read_sysfs_int(d->sysfs_entry, "gbphy_firmware_latency_min");
358                 r->gbphy_firmware_latency_max =
359                         read_sysfs_int(d->sysfs_entry, "gbphy_firmware_latency_max");
360                 r->gbphy_firmware_latency_avg =
361                         read_sysfs_float(d->sysfs_entry, "gbphy_firmware_latency_avg");
362
363                 r->request_jitter = r->request_max - r->request_min;
364                 r->latency_jitter = r->latency_max - r->latency_min;
365                 r->throughput_jitter = r->throughput_max - r->throughput_min;
366                 r->apbridge_unipro_latency_jitter =
367                         r->apbridge_unipro_latency_max - r->apbridge_unipro_latency_min;
368                 r->gbphy_firmware_latency_jitter =
369                         r->gbphy_firmware_latency_max - r->gbphy_firmware_latency_min;
370
371         }
372
373         /*calculate the aggregate results of all enabled devices */
374         if (t->aggregate_output) {
375                 r = &t->aggregate_results;
376
377                 r->request_min = get_request_min_aggregate(t);
378                 r->request_max = get_request_max_aggregate(t);
379                 r->request_avg = get_request_avg_aggregate(t);
380
381                 r->latency_min = get_latency_min_aggregate(t);
382                 r->latency_max = get_latency_max_aggregate(t);
383                 r->latency_avg = get_latency_avg_aggregate(t);
384
385                 r->throughput_min = get_throughput_min_aggregate(t);
386                 r->throughput_max = get_throughput_max_aggregate(t);
387                 r->throughput_avg = get_throughput_avg_aggregate(t);
388
389                 r->apbridge_unipro_latency_min =
390                         get_apbridge_unipro_latency_min_aggregate(t);
391                 r->apbridge_unipro_latency_max =
392                         get_apbridge_unipro_latency_max_aggregate(t);
393                 r->apbridge_unipro_latency_avg =
394                         get_apbridge_unipro_latency_avg_aggregate(t);
395
396                 r->gbphy_firmware_latency_min =
397                         get_gbphy_firmware_latency_min_aggregate(t);
398                 r->gbphy_firmware_latency_max =
399                         get_gbphy_firmware_latency_max_aggregate(t);
400                 r->gbphy_firmware_latency_avg =
401                         get_gbphy_firmware_latency_avg_aggregate(t);
402
403                 r->request_jitter = r->request_max - r->request_min;
404                 r->latency_jitter = r->latency_max - r->latency_min;
405                 r->throughput_jitter = r->throughput_max - r->throughput_min;
406                 r->apbridge_unipro_latency_jitter =
407                         r->apbridge_unipro_latency_max - r->apbridge_unipro_latency_min;
408                 r->gbphy_firmware_latency_jitter =
409                         r->gbphy_firmware_latency_max - r->gbphy_firmware_latency_min;
410
411         }
412
413         return 0;
414 }
415
416 int format_output(struct loopback_test *t,
417                   struct loopback_results *r,
418                   const char *dev_name,
419                   char *buf, int buf_len,
420                   struct tm *tm)
421 {
422         int len = 0;
423
424         memset(buf, 0x00, buf_len);
425         len = snprintf(buf, buf_len, "%u-%u-%u %u:%u:%u",
426                        tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
427                        tm->tm_hour, tm->tm_min, tm->tm_sec);
428
429         if (t->porcelain) {
430                 len += snprintf(&buf[len], buf_len - len,
431                         "\n test:\t\t\t%s\n path:\t\t\t%s\n size:\t\t\t%u\n iterations:\t\t%u\n errors:\t\t%u\n async:\t\t\t%s\n",
432                         t->test_name,
433                         dev_name,
434                         t->size,
435                         t->iteration_max,
436                         r->error,
437                         t->use_async ? "Enabled" : "Disabled");
438
439                 len += snprintf(&buf[len], buf_len - len,
440                         " requests per-sec:\tmin=%u, max=%u, average=%f, jitter=%u\n",
441                         r->request_min,
442                         r->request_max,
443                         r->request_avg,
444                         r->request_jitter);
445
446                 len += snprintf(&buf[len], buf_len - len,
447                         " ap-throughput B/s:\tmin=%u max=%u average=%f jitter=%u\n",
448                         r->throughput_min,
449                         r->throughput_max,
450                         r->throughput_avg,
451                         r->throughput_jitter);
452                 len += snprintf(&buf[len], buf_len - len,
453                         " ap-latency usec:\tmin=%u max=%u average=%f jitter=%u\n",
454                         r->latency_min,
455                         r->latency_max,
456                         r->latency_avg,
457                         r->latency_jitter);
458                 len += snprintf(&buf[len], buf_len - len,
459                         " apbridge-latency usec:\tmin=%u max=%u average=%f jitter=%u\n",
460                         r->apbridge_unipro_latency_min,
461                         r->apbridge_unipro_latency_max,
462                         r->apbridge_unipro_latency_avg,
463                         r->apbridge_unipro_latency_jitter);
464
465                 len += snprintf(&buf[len], buf_len - len,
466                         " gbphy-latency usec:\tmin=%u max=%u average=%f jitter=%u\n",
467                         r->gbphy_firmware_latency_min,
468                         r->gbphy_firmware_latency_max,
469                         r->gbphy_firmware_latency_avg,
470                         r->gbphy_firmware_latency_jitter);
471
472         } else {
473                 len += snprintf(&buf[len], buf_len - len, ",%s,%s,%u,%u,%u",
474                         t->test_name, dev_name, t->size, t->iteration_max,
475                         r->error);
476
477                 len += snprintf(&buf[len], buf_len - len, ",%u,%u,%f,%u",
478                         r->request_min,
479                         r->request_max,
480                         r->request_avg,
481                         r->request_jitter);
482
483                 len += snprintf(&buf[len], buf_len - len, ",%u,%u,%f,%u",
484                         r->latency_min,
485                         r->latency_max,
486                         r->latency_avg,
487                         r->latency_jitter);
488
489                 len += snprintf(&buf[len], buf_len - len, ",%u,%u,%f,%u",
490                         r->throughput_min,
491                         r->throughput_max,
492                         r->throughput_avg,
493                         r->throughput_jitter);
494
495                 len += snprintf(&buf[len], buf_len - len, ",%u,%u,%f,%u",
496                         r->apbridge_unipro_latency_min,
497                         r->apbridge_unipro_latency_max,
498                         r->apbridge_unipro_latency_avg,
499                         r->apbridge_unipro_latency_jitter);
500
501                 len += snprintf(&buf[len], buf_len - len, ",%u,%u,%f,%u",
502                         r->gbphy_firmware_latency_min,
503                         r->gbphy_firmware_latency_max,
504                         r->gbphy_firmware_latency_avg,
505                         r->gbphy_firmware_latency_jitter);
506         }
507
508         printf("\n%s\n", buf);
509
510         return len;
511 }
512
513 static int log_results(struct loopback_test *t)
514 {
515         int fd, i, len, ret;
516         struct tm tm;
517         time_t local_time;
518         char file_name[MAX_SYSFS_PATH];
519         char data[CSV_MAX_LINE];
520
521         local_time = time(NULL);
522         tm = *localtime(&local_time);
523
524         /*
525          * file name will test_name_size_iteration_max.csv
526          * every time the same test with the same parameters is run we will then
527          * append to the same CSV with datestamp - representing each test
528          * dataset.
529          */
530         if (t->file_output && !t->porcelain) {
531                 snprintf(file_name, sizeof(file_name), "%s_%d_%d.csv",
532                          t->test_name, t->size, t->iteration_max);
533
534                 fd = open(file_name, O_WRONLY | O_CREAT | O_APPEND, 0644);
535                 if (fd < 0) {
536                         fprintf(stderr, "unable to open %s for appendation\n", file_name);
537                         abort();
538                 }
539
540         }
541         for (i = 0; i < t->device_count; i++) {
542                 if (!device_enabled(t, i))
543                         continue;
544
545                 len = format_output(t, &t->devices[i].results,
546                                     t->devices[i].name,
547                                     data, sizeof(data), &tm);
548                 if (t->file_output && !t->porcelain) {
549                         ret = write(fd, data, len);
550                         if (ret == -1)
551                                 fprintf(stderr, "unable to write %d bytes to csv.\n", len);
552                 }
553
554         }
555
556
557         if (t->aggregate_output) {
558                 len = format_output(t, &t->aggregate_results, "aggregate",
559                                     data, sizeof(data), &tm);
560                 if (t->file_output && !t->porcelain) {
561                         ret = write(fd, data, len);
562                         if (ret == -1)
563                                 fprintf(stderr, "unable to write %d bytes to csv.\n", len);
564                 }
565         }
566
567         if (t->file_output && !t->porcelain)
568                 close(fd);
569
570         return 0;
571 }
572
573 int is_loopback_device(const char *path, const char *node)
574 {
575         char file[MAX_SYSFS_PATH];
576
577         snprintf(file, MAX_SYSFS_PATH, "%s%s/iteration_count", path, node);
578         if (access(file, F_OK) == 0)
579                 return 1;
580         return 0;
581 }
582
583 int find_loopback_devices(struct loopback_test *t)
584 {
585         struct dirent **namelist;
586         int i, n, ret;
587         unsigned int dev_id;
588         struct loopback_device *d;
589
590         n = scandir(t->sysfs_prefix, &namelist, NULL, alphasort);
591         if (n < 0) {
592                 perror("scandir");
593                 ret = -ENODEV;
594                 goto baddir;
595         }
596
597         /* Don't include '.' and '..' */
598         if (n <= 2) {
599                 ret = -ENOMEM;
600                 goto done;
601         }
602
603         for (i = 0; i < n; i++) {
604                 ret = sscanf(namelist[i]->d_name, "gb_loopback%u", &dev_id);
605                 if (ret != 1)
606                         continue;
607
608                 if (!is_loopback_device(t->sysfs_prefix, namelist[i]->d_name))
609                         continue;
610
611                 if (t->device_count == MAX_NUM_DEVICES) {
612                         fprintf(stderr, "max number of devices reached!\n");
613                         break;
614                 }
615
616                 d = &t->devices[t->device_count++];
617                 snprintf(d->name, MAX_STR_LEN, "gb_loopback%u", dev_id);
618
619                 snprintf(d->sysfs_entry, MAX_SYSFS_PATH, "%s%s/",
620                          t->sysfs_prefix, d->name);
621
622                 snprintf(d->debugfs_entry, MAX_SYSFS_PATH, "%sraw_latency_%s",
623                          t->debugfs_prefix, d->name);
624
625                 if (t->debug)
626                         printf("add %s %s\n", d->sysfs_entry, d->debugfs_entry);
627         }
628
629         ret = 0;
630 done:
631         for (i = 0; i < n; i++)
632                 free(namelist[i]);
633         free(namelist);
634 baddir:
635         return ret;
636 }
637
638 static int open_poll_files(struct loopback_test *t)
639 {
640         struct loopback_device *dev;
641         char buf[MAX_SYSFS_PATH + MAX_STR_LEN];
642         char dummy;
643         int fds_idx = 0;
644         int i;
645
646         for (i = 0; i < t->device_count; i++) {
647                 dev = &t->devices[i];
648
649                 if (!device_enabled(t, i))
650                         continue;
651
652                 snprintf(buf, sizeof(buf), "%s%s", dev->sysfs_entry, "iteration_count");
653                 t->fds[fds_idx].fd = open(buf, O_RDONLY);
654                 if (t->fds[fds_idx].fd < 0) {
655                         fprintf(stderr, "Error opening poll file!\n");
656                         goto err;
657                 }
658                 read(t->fds[fds_idx].fd, &dummy, 1);
659                 t->fds[fds_idx].events = POLLERR | POLLPRI;
660                 t->fds[fds_idx].revents = 0;
661                 fds_idx++;
662         }
663
664         t->poll_count = fds_idx;
665
666         return 0;
667
668 err:
669         for (i = 0; i < fds_idx; i++)
670                 close(t->fds[i].fd);
671
672         return -1;
673 }
674
675 static int close_poll_files(struct loopback_test *t)
676 {
677         int i;
678         for (i = 0; i < t->poll_count; i++)
679                 close(t->fds[i].fd);
680
681         return 0;
682 }
683 static int is_complete(struct loopback_test *t)
684 {
685         int iteration_count;
686         int i;
687
688         for (i = 0; i < t->device_count; i++) {
689                 if (!device_enabled(t, i))
690                         continue;
691
692                 iteration_count = read_sysfs_int(t->devices[i].sysfs_entry,
693                                                  "iteration_count");
694
695                 /* at least one device did not finish yet */
696                 if (iteration_count != t->iteration_max)
697                         return 0;
698         }
699
700         return 1;
701 }
702
703 static void stop_tests(struct loopback_test *t)
704 {
705         int i;
706
707         for (i = 0; i < t->device_count; i++) {
708                 if (!device_enabled(t, i))
709                         continue;
710                 write_sysfs_val(t->devices[i].sysfs_entry, "type", 0);
711         }
712 }
713
714 static void handler(int sig) { /* do nothing */  }
715
716 static int wait_for_complete(struct loopback_test *t)
717 {
718         int number_of_events = 0;
719         char dummy;
720         int ret;
721         int i;
722         struct timespec *ts = NULL;
723         struct sigaction sa;
724         sigset_t mask_old, mask;
725
726         sigemptyset(&mask);
727         sigemptyset(&mask_old);
728         sigaddset(&mask, SIGINT);
729         sigprocmask(SIG_BLOCK, &mask, &mask_old);
730
731         sa.sa_handler = handler;
732         sa.sa_flags = 0;
733         sigemptyset(&sa.sa_mask);
734         if (sigaction(SIGINT, &sa, NULL) == -1) {
735                 fprintf(stderr, "sigaction error\n");
736                 return -1;
737         }
738
739         if (t->poll_timeout.tv_sec != 0)
740                 ts = &t->poll_timeout;
741
742         while (1) {
743
744                 ret = ppoll(t->fds, t->poll_count, ts, &mask_old);
745                 if (ret <= 0) {
746                         stop_tests(t);
747                         fprintf(stderr, "Poll exit with errno %d\n", errno);
748                         return -1;
749                 }
750
751                 for (i = 0; i < t->poll_count; i++) {
752                         if (t->fds[i].revents & POLLPRI) {
753                                 /* Dummy read to clear the event */
754                                 read(t->fds[i].fd, &dummy, 1);
755                                 number_of_events++;
756                         }
757                 }
758
759                 if (number_of_events == t->poll_count)
760                         break;
761         }
762
763         if (!is_complete(t)) {
764                 fprintf(stderr, "Iteration count did not finish!\n");
765                 return -1;
766         }
767
768         return 0;
769 }
770
771 static void prepare_devices(struct loopback_test *t)
772 {
773         int i;
774
775         /*
776          * Cancel any running tests on enabled devices. If
777          * stop_all option is given, stop test on all devices.
778          */
779         for (i = 0; i < t->device_count; i++)
780                 if (t->stop_all || device_enabled(t, i))
781                         write_sysfs_val(t->devices[i].sysfs_entry, "type", 0);
782
783
784         for (i = 0; i < t->device_count; i++) {
785                 if (!device_enabled(t, i))
786                         continue;
787
788                 write_sysfs_val(t->devices[i].sysfs_entry, "us_wait",
789                                 t->us_wait);
790
791                 /* Set operation size */
792                 write_sysfs_val(t->devices[i].sysfs_entry, "size", t->size);
793
794                 /* Set iterations */
795                 write_sysfs_val(t->devices[i].sysfs_entry, "iteration_max",
796                                 t->iteration_max);
797
798                 if (t->use_async) {
799                         write_sysfs_val(t->devices[i].sysfs_entry, "async", 1);
800                         write_sysfs_val(t->devices[i].sysfs_entry,
801                                         "timeout", t->async_timeout);
802                         write_sysfs_val(t->devices[i].sysfs_entry,
803                                         "outstanding_operations_max",
804                                         t->async_outstanding_operations);
805                 } else
806                         write_sysfs_val(t->devices[i].sysfs_entry, "async", 0);
807         }
808 }
809
810 static int start(struct loopback_test *t)
811 {
812         int i;
813
814         /* the test starts by writing test_id to the type file. */
815         for (i = 0; i < t->device_count; i++) {
816                 if (!device_enabled(t, i))
817                         continue;
818
819                 write_sysfs_val(t->devices[i].sysfs_entry, "type", t->test_id);
820         }
821
822         return 0;
823 }
824
825
826 void loopback_run(struct loopback_test *t)
827 {
828         int i;
829         int ret;
830
831         for (i = 0; dict[i].name != NULL; i++) {
832                 if (strstr(dict[i].name, t->test_name))
833                         t->test_id = dict[i].type;
834         }
835         if (!t->test_id) {
836                 fprintf(stderr, "invalid test %s\n", t->test_name);
837                 usage();
838                 return;
839         }
840
841         prepare_devices(t);
842
843         ret = open_poll_files(t);
844         if (ret)
845                 goto err;
846
847         start(t);
848
849         ret = wait_for_complete(t);
850         close_poll_files(t);
851         if (ret)
852                 goto err;
853
854
855         get_results(t);
856
857         log_results(t);
858
859         return;
860
861 err:
862         printf("Error running test\n");
863         return;
864 }
865
866 static int sanity_check(struct loopback_test *t)
867 {
868         int i;
869
870         if (t->device_count == 0) {
871                 fprintf(stderr, "No loopback devices found\n");
872                 return -1;
873         }
874
875         for (i = 0; i < MAX_NUM_DEVICES; i++) {
876                 if (!device_enabled(t, i))
877                         continue;
878
879                 if (t->mask && !strcmp(t->devices[i].name, "")) {
880                         fprintf(stderr, "Bad device mask %x\n", (1 << i));
881                         return -1;
882                 }
883
884         }
885
886
887         return 0;
888 }
889
890 int main(int argc, char *argv[])
891 {
892         int o, ret;
893         char *sysfs_prefix = "/sys/class/gb_loopback/";
894         char *debugfs_prefix = "/sys/kernel/debug/gb_loopback/";
895
896         memset(&t, 0, sizeof(t));
897
898         while ((o = getopt(argc, argv,
899                            "t:s:i:S:D:m:v::d::r::p::a::l::x::o:O:c:w:z::f::")) != -1) {
900                 switch (o) {
901                 case 't':
902                         snprintf(t.test_name, MAX_STR_LEN, "%s", optarg);
903                         break;
904                 case 's':
905                         t.size = atoi(optarg);
906                         break;
907                 case 'i':
908                         t.iteration_max = atoi(optarg);
909                         break;
910                 case 'S':
911                         snprintf(t.sysfs_prefix, MAX_SYSFS_PREFIX, "%s", optarg);
912                         break;
913                 case 'D':
914                         snprintf(t.debugfs_prefix, MAX_SYSFS_PREFIX, "%s", optarg);
915                         break;
916                 case 'm':
917                         t.mask = atol(optarg);
918                         break;
919                 case 'v':
920                         t.verbose = 1;
921                         break;
922                 case 'd':
923                         t.debug = 1;
924                         break;
925                 case 'r':
926                         t.raw_data_dump = 1;
927                         break;
928                 case 'p':
929                         t.porcelain = 1;
930                         break;
931                 case 'a':
932                         t.aggregate_output = 1;
933                         break;
934                 case 'l':
935                         t.list_devices = 1;
936                         break;
937                 case 'x':
938                         t.use_async = 1;
939                         break;
940                 case 'o':
941                         t.async_timeout = atoi(optarg);
942                         break;
943                 case 'O':
944                         t.poll_timeout.tv_sec = atoi(optarg);
945                         break;
946                 case 'c':
947                         t.async_outstanding_operations = atoi(optarg);
948                         break;
949                 case 'w':
950                         t.us_wait = atoi(optarg);
951                         break;
952                 case 'z':
953                         t.file_output = 1;
954                         break;
955                 case 'f':
956                         t.stop_all = 1;
957                         break;
958                 default:
959                         usage();
960                         return -EINVAL;
961                 }
962         }
963
964         if (!strcmp(t.sysfs_prefix, ""))
965                 snprintf(t.sysfs_prefix, MAX_SYSFS_PREFIX, "%s", sysfs_prefix);
966
967         if (!strcmp(t.debugfs_prefix, ""))
968                 snprintf(t.debugfs_prefix, MAX_SYSFS_PREFIX, "%s", debugfs_prefix);
969
970         ret = find_loopback_devices(&t);
971         if (ret)
972                 return ret;
973         ret = sanity_check(&t);
974         if (ret)
975                 return ret;
976
977         if (t.list_devices) {
978                 show_loopback_devices(&t);
979                 return 0;
980         }
981
982         if (t.test_name[0] == '\0' || t.iteration_max == 0)
983                 usage();
984
985         if (t.async_timeout == 0)
986                 t.async_timeout = DEFAULT_ASYNC_TIMEOUT;
987
988         loopback_run(&t);
989
990         return 0;
991 }