OSDN Git Service

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