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