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 
abort(void)171 void abort(void)
172 {
173 	_exit(1);
174 }
175 
usage(void)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 
device_enabled(struct loopback_test * t,int dev_idx)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 
show_loopback_devices(struct loopback_test * t)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 
open_sysfs(const char * sys_pfx,const char * node,int flags)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 
read_sysfs_int_fd(int fd,const char * sys_pfx,const char * node)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 
read_sysfs_float_fd(int fd,const char * sys_pfx,const char * node)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 		fprintf(stderr, "unable to read from %s%s %s\n", sys_pfx, node,
277 			strerror(errno));
278 		close(fd);
279 		abort();
280 	}
281 	return atof(buf);
282 }
283 
read_sysfs_int(const char * sys_pfx,const char * node)284 int read_sysfs_int(const char *sys_pfx, const char *node)
285 {
286 	int fd, val;
287 
288 	fd = open_sysfs(sys_pfx, node, O_RDONLY);
289 	val = read_sysfs_int_fd(fd, sys_pfx, node);
290 	close(fd);
291 	return val;
292 }
293 
read_sysfs_float(const char * sys_pfx,const char * node)294 float read_sysfs_float(const char *sys_pfx, const char *node)
295 {
296 	int fd;
297 	float val;
298 
299 	fd = open_sysfs(sys_pfx, node, O_RDONLY);
300 	val = read_sysfs_float_fd(fd, sys_pfx, node);
301 	close(fd);
302 	return val;
303 }
304 
write_sysfs_val(const char * sys_pfx,const char * node,int val)305 void write_sysfs_val(const char *sys_pfx, const char *node, int val)
306 {
307 	int fd, len;
308 	char buf[SYSFS_MAX_INT];
309 
310 	fd = open_sysfs(sys_pfx, node, O_RDWR);
311 	len = snprintf(buf, sizeof(buf), "%d", val);
312 	if (write(fd, buf, len) < 0) {
313 		fprintf(stderr, "unable to write to %s%s %s\n", sys_pfx, node,
314 			strerror(errno));
315 		close(fd);
316 		abort();
317 	}
318 	close(fd);
319 }
320 
get_results(struct loopback_test * t)321 static int get_results(struct loopback_test *t)
322 {
323 	struct loopback_device *d;
324 	struct loopback_results *r;
325 	int i;
326 
327 	for (i = 0; i < t->device_count; i++) {
328 		if (!device_enabled(t, i))
329 			continue;
330 
331 		d = &t->devices[i];
332 		r = &d->results;
333 
334 		r->error = read_sysfs_int(d->sysfs_entry, "error");
335 		r->request_min = read_sysfs_int(d->sysfs_entry, "requests_per_second_min");
336 		r->request_max = read_sysfs_int(d->sysfs_entry, "requests_per_second_max");
337 		r->request_avg = read_sysfs_float(d->sysfs_entry, "requests_per_second_avg");
338 
339 		r->latency_min = read_sysfs_int(d->sysfs_entry, "latency_min");
340 		r->latency_max = read_sysfs_int(d->sysfs_entry, "latency_max");
341 		r->latency_avg = read_sysfs_float(d->sysfs_entry, "latency_avg");
342 
343 		r->throughput_min = read_sysfs_int(d->sysfs_entry, "throughput_min");
344 		r->throughput_max = read_sysfs_int(d->sysfs_entry, "throughput_max");
345 		r->throughput_avg = read_sysfs_float(d->sysfs_entry, "throughput_avg");
346 
347 		r->apbridge_unipro_latency_min =
348 			read_sysfs_int(d->sysfs_entry, "apbridge_unipro_latency_min");
349 		r->apbridge_unipro_latency_max =
350 			read_sysfs_int(d->sysfs_entry, "apbridge_unipro_latency_max");
351 		r->apbridge_unipro_latency_avg =
352 			read_sysfs_float(d->sysfs_entry, "apbridge_unipro_latency_avg");
353 
354 		r->gbphy_firmware_latency_min =
355 			read_sysfs_int(d->sysfs_entry, "gbphy_firmware_latency_min");
356 		r->gbphy_firmware_latency_max =
357 			read_sysfs_int(d->sysfs_entry, "gbphy_firmware_latency_max");
358 		r->gbphy_firmware_latency_avg =
359 			read_sysfs_float(d->sysfs_entry, "gbphy_firmware_latency_avg");
360 
361 		r->request_jitter = r->request_max - r->request_min;
362 		r->latency_jitter = r->latency_max - r->latency_min;
363 		r->throughput_jitter = r->throughput_max - r->throughput_min;
364 		r->apbridge_unipro_latency_jitter =
365 			r->apbridge_unipro_latency_max - r->apbridge_unipro_latency_min;
366 		r->gbphy_firmware_latency_jitter =
367 			r->gbphy_firmware_latency_max - r->gbphy_firmware_latency_min;
368 	}
369 
370 	/*calculate the aggregate results of all enabled devices */
371 	if (t->aggregate_output) {
372 		r = &t->aggregate_results;
373 
374 		r->request_min = get_request_min_aggregate(t);
375 		r->request_max = get_request_max_aggregate(t);
376 		r->request_avg = get_request_avg_aggregate(t);
377 
378 		r->latency_min = get_latency_min_aggregate(t);
379 		r->latency_max = get_latency_max_aggregate(t);
380 		r->latency_avg = get_latency_avg_aggregate(t);
381 
382 		r->throughput_min = get_throughput_min_aggregate(t);
383 		r->throughput_max = get_throughput_max_aggregate(t);
384 		r->throughput_avg = get_throughput_avg_aggregate(t);
385 
386 		r->apbridge_unipro_latency_min =
387 			get_apbridge_unipro_latency_min_aggregate(t);
388 		r->apbridge_unipro_latency_max =
389 			get_apbridge_unipro_latency_max_aggregate(t);
390 		r->apbridge_unipro_latency_avg =
391 			get_apbridge_unipro_latency_avg_aggregate(t);
392 
393 		r->gbphy_firmware_latency_min =
394 			get_gbphy_firmware_latency_min_aggregate(t);
395 		r->gbphy_firmware_latency_max =
396 			get_gbphy_firmware_latency_max_aggregate(t);
397 		r->gbphy_firmware_latency_avg =
398 			get_gbphy_firmware_latency_avg_aggregate(t);
399 
400 		r->request_jitter = r->request_max - r->request_min;
401 		r->latency_jitter = r->latency_max - r->latency_min;
402 		r->throughput_jitter = r->throughput_max - r->throughput_min;
403 		r->apbridge_unipro_latency_jitter =
404 			r->apbridge_unipro_latency_max - r->apbridge_unipro_latency_min;
405 		r->gbphy_firmware_latency_jitter =
406 			r->gbphy_firmware_latency_max - r->gbphy_firmware_latency_min;
407 	}
408 
409 	return 0;
410 }
411 
format_output(struct loopback_test * t,struct loopback_results * r,const char * dev_name,char * buf,int buf_len,struct tm * tm)412 int format_output(struct loopback_test *t,
413 		  struct loopback_results *r,
414 		  const char *dev_name,
415 		  char *buf, int buf_len,
416 		  struct tm *tm)
417 {
418 	int len = 0;
419 
420 	memset(buf, 0x00, buf_len);
421 	len = snprintf(buf, buf_len, "%u-%u-%u %u:%u:%u",
422 		       tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
423 		       tm->tm_hour, tm->tm_min, tm->tm_sec);
424 
425 	if (t->porcelain) {
426 		len += snprintf(&buf[len], buf_len - len,
427 			"\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",
428 			t->test_name,
429 			dev_name,
430 			t->size,
431 			t->iteration_max,
432 			r->error,
433 			t->use_async ? "Enabled" : "Disabled");
434 
435 		len += snprintf(&buf[len], buf_len - len,
436 			" requests per-sec:\tmin=%u, max=%u, average=%f, jitter=%u\n",
437 			r->request_min,
438 			r->request_max,
439 			r->request_avg,
440 			r->request_jitter);
441 
442 		len += snprintf(&buf[len], buf_len - len,
443 			" ap-throughput B/s:\tmin=%u max=%u average=%f jitter=%u\n",
444 			r->throughput_min,
445 			r->throughput_max,
446 			r->throughput_avg,
447 			r->throughput_jitter);
448 		len += snprintf(&buf[len], buf_len - len,
449 			" ap-latency usec:\tmin=%u max=%u average=%f jitter=%u\n",
450 			r->latency_min,
451 			r->latency_max,
452 			r->latency_avg,
453 			r->latency_jitter);
454 		len += snprintf(&buf[len], buf_len - len,
455 			" apbridge-latency usec:\tmin=%u max=%u average=%f jitter=%u\n",
456 			r->apbridge_unipro_latency_min,
457 			r->apbridge_unipro_latency_max,
458 			r->apbridge_unipro_latency_avg,
459 			r->apbridge_unipro_latency_jitter);
460 
461 		len += snprintf(&buf[len], buf_len - len,
462 			" gbphy-latency usec:\tmin=%u max=%u average=%f jitter=%u\n",
463 			r->gbphy_firmware_latency_min,
464 			r->gbphy_firmware_latency_max,
465 			r->gbphy_firmware_latency_avg,
466 			r->gbphy_firmware_latency_jitter);
467 
468 	} else {
469 		len += snprintf(&buf[len], buf_len - len, ",%s,%s,%u,%u,%u",
470 			t->test_name, dev_name, t->size, t->iteration_max,
471 			r->error);
472 
473 		len += snprintf(&buf[len], buf_len - len, ",%u,%u,%f,%u",
474 			r->request_min,
475 			r->request_max,
476 			r->request_avg,
477 			r->request_jitter);
478 
479 		len += snprintf(&buf[len], buf_len - len, ",%u,%u,%f,%u",
480 			r->latency_min,
481 			r->latency_max,
482 			r->latency_avg,
483 			r->latency_jitter);
484 
485 		len += snprintf(&buf[len], buf_len - len, ",%u,%u,%f,%u",
486 			r->throughput_min,
487 			r->throughput_max,
488 			r->throughput_avg,
489 			r->throughput_jitter);
490 
491 		len += snprintf(&buf[len], buf_len - len, ",%u,%u,%f,%u",
492 			r->apbridge_unipro_latency_min,
493 			r->apbridge_unipro_latency_max,
494 			r->apbridge_unipro_latency_avg,
495 			r->apbridge_unipro_latency_jitter);
496 
497 		len += snprintf(&buf[len], buf_len - len, ",%u,%u,%f,%u",
498 			r->gbphy_firmware_latency_min,
499 			r->gbphy_firmware_latency_max,
500 			r->gbphy_firmware_latency_avg,
501 			r->gbphy_firmware_latency_jitter);
502 	}
503 
504 	printf("\n%s\n", buf);
505 
506 	return len;
507 }
508 
log_results(struct loopback_test * t)509 static int log_results(struct loopback_test *t)
510 {
511 	int fd, i, len, ret;
512 	struct tm tm;
513 	time_t local_time;
514 	char file_name[MAX_SYSFS_PATH];
515 	char data[CSV_MAX_LINE];
516 
517 	local_time = time(NULL);
518 	tm = *localtime(&local_time);
519 
520 	/*
521 	 * file name will test_name_size_iteration_max.csv
522 	 * every time the same test with the same parameters is run we will then
523 	 * append to the same CSV with datestamp - representing each test
524 	 * dataset.
525 	 */
526 	if (t->file_output && !t->porcelain) {
527 		snprintf(file_name, sizeof(file_name), "%s_%d_%d.csv",
528 			 t->test_name, t->size, t->iteration_max);
529 
530 		fd = open(file_name, O_WRONLY | O_CREAT | O_APPEND, 0644);
531 		if (fd < 0) {
532 			fprintf(stderr, "unable to open %s for appending\n", file_name);
533 			abort();
534 		}
535 	}
536 	for (i = 0; i < t->device_count; i++) {
537 		if (!device_enabled(t, i))
538 			continue;
539 
540 		len = format_output(t, &t->devices[i].results,
541 				    t->devices[i].name,
542 				    data, sizeof(data), &tm);
543 		if (t->file_output && !t->porcelain) {
544 			ret = write(fd, data, len);
545 			if (ret == -1)
546 				fprintf(stderr, "unable to write %d bytes to csv.\n", len);
547 		}
548 	}
549 
550 	if (t->aggregate_output) {
551 		len = format_output(t, &t->aggregate_results, "aggregate",
552 				    data, sizeof(data), &tm);
553 		if (t->file_output && !t->porcelain) {
554 			ret = write(fd, data, len);
555 			if (ret == -1)
556 				fprintf(stderr, "unable to write %d bytes to csv.\n", len);
557 		}
558 	}
559 
560 	if (t->file_output && !t->porcelain)
561 		close(fd);
562 
563 	return 0;
564 }
565 
is_loopback_device(const char * path,const char * node)566 int is_loopback_device(const char *path, const char *node)
567 {
568 	char file[MAX_SYSFS_PATH];
569 
570 	snprintf(file, MAX_SYSFS_PATH, "%s%s/iteration_count", path, node);
571 	if (access(file, F_OK) == 0)
572 		return 1;
573 	return 0;
574 }
575 
find_loopback_devices(struct loopback_test * t)576 int find_loopback_devices(struct loopback_test *t)
577 {
578 	struct dirent **namelist;
579 	int i, n, ret;
580 	unsigned int dev_id;
581 	struct loopback_device *d;
582 
583 	n = scandir(t->sysfs_prefix, &namelist, NULL, alphasort);
584 	if (n < 0) {
585 		perror("scandir");
586 		ret = -ENODEV;
587 		goto baddir;
588 	}
589 
590 	/* Don't include '.' and '..' */
591 	if (n <= 2) {
592 		ret = -ENOMEM;
593 		goto done;
594 	}
595 
596 	for (i = 0; i < n; i++) {
597 		ret = sscanf(namelist[i]->d_name, "gb_loopback%u", &dev_id);
598 		if (ret != 1)
599 			continue;
600 
601 		if (!is_loopback_device(t->sysfs_prefix, namelist[i]->d_name))
602 			continue;
603 
604 		if (t->device_count == MAX_NUM_DEVICES) {
605 			fprintf(stderr, "max number of devices reached!\n");
606 			break;
607 		}
608 
609 		d = &t->devices[t->device_count++];
610 		snprintf(d->name, MAX_STR_LEN, "gb_loopback%u", dev_id);
611 
612 		snprintf(d->sysfs_entry, MAX_SYSFS_PATH, "%s%s/",
613 			 t->sysfs_prefix, d->name);
614 
615 		snprintf(d->debugfs_entry, MAX_SYSFS_PATH, "%sraw_latency_%s",
616 			 t->debugfs_prefix, d->name);
617 
618 		if (t->debug)
619 			printf("add %s %s\n", d->sysfs_entry, d->debugfs_entry);
620 	}
621 
622 	ret = 0;
623 done:
624 	for (i = 0; i < n; i++)
625 		free(namelist[i]);
626 	free(namelist);
627 baddir:
628 	return ret;
629 }
630 
open_poll_files(struct loopback_test * t)631 static int open_poll_files(struct loopback_test *t)
632 {
633 	struct loopback_device *dev;
634 	char buf[MAX_SYSFS_PATH + MAX_STR_LEN];
635 	char dummy;
636 	int fds_idx = 0;
637 	int i;
638 
639 	for (i = 0; i < t->device_count; i++) {
640 		dev = &t->devices[i];
641 
642 		if (!device_enabled(t, i))
643 			continue;
644 
645 		snprintf(buf, sizeof(buf), "%s%s", dev->sysfs_entry, "iteration_count");
646 		t->fds[fds_idx].fd = open(buf, O_RDONLY);
647 		if (t->fds[fds_idx].fd < 0) {
648 			fprintf(stderr, "Error opening poll file!\n");
649 			goto err;
650 		}
651 		read(t->fds[fds_idx].fd, &dummy, 1);
652 		t->fds[fds_idx].events = POLLERR | POLLPRI;
653 		t->fds[fds_idx].revents = 0;
654 		fds_idx++;
655 	}
656 
657 	t->poll_count = fds_idx;
658 
659 	return 0;
660 
661 err:
662 	for (i = 0; i < fds_idx; i++)
663 		close(t->fds[i].fd);
664 
665 	return -1;
666 }
667 
close_poll_files(struct loopback_test * t)668 static int close_poll_files(struct loopback_test *t)
669 {
670 	int i;
671 
672 	for (i = 0; i < t->poll_count; i++)
673 		close(t->fds[i].fd);
674 
675 	return 0;
676 }
is_complete(struct loopback_test * t)677 static int is_complete(struct loopback_test *t)
678 {
679 	int iteration_count;
680 	int i;
681 
682 	for (i = 0; i < t->device_count; i++) {
683 		if (!device_enabled(t, i))
684 			continue;
685 
686 		iteration_count = read_sysfs_int(t->devices[i].sysfs_entry,
687 						 "iteration_count");
688 
689 		/* at least one device did not finish yet */
690 		if (iteration_count != t->iteration_max)
691 			return 0;
692 	}
693 
694 	return 1;
695 }
696 
stop_tests(struct loopback_test * t)697 static void stop_tests(struct loopback_test *t)
698 {
699 	int i;
700 
701 	for (i = 0; i < t->device_count; i++) {
702 		if (!device_enabled(t, i))
703 			continue;
704 		write_sysfs_val(t->devices[i].sysfs_entry, "type", 0);
705 	}
706 }
707 
handler(int sig)708 static void handler(int sig) { /* do nothing */  }
709 
wait_for_complete(struct loopback_test * t)710 static int wait_for_complete(struct loopback_test *t)
711 {
712 	int number_of_events = 0;
713 	char dummy;
714 	int ret;
715 	int i;
716 	struct timespec *ts = NULL;
717 	struct sigaction sa;
718 	sigset_t mask_old, mask;
719 
720 	sigemptyset(&mask);
721 	sigemptyset(&mask_old);
722 	sigaddset(&mask, SIGINT);
723 	sigprocmask(SIG_BLOCK, &mask, &mask_old);
724 
725 	sa.sa_handler = handler;
726 	sa.sa_flags = 0;
727 	sigemptyset(&sa.sa_mask);
728 	if (sigaction(SIGINT, &sa, NULL) == -1) {
729 		fprintf(stderr, "sigaction error\n");
730 		return -1;
731 	}
732 
733 	if (t->poll_timeout.tv_sec != 0)
734 		ts = &t->poll_timeout;
735 
736 	while (1) {
737 		ret = ppoll(t->fds, t->poll_count, ts, &mask_old);
738 		if (ret <= 0) {
739 			stop_tests(t);
740 			fprintf(stderr, "Poll exit with errno %d\n", errno);
741 			return -1;
742 		}
743 
744 		for (i = 0; i < t->poll_count; i++) {
745 			if (t->fds[i].revents & POLLPRI) {
746 				/* Dummy read to clear the event */
747 				read(t->fds[i].fd, &dummy, 1);
748 				number_of_events++;
749 			}
750 		}
751 
752 		if (number_of_events == t->poll_count)
753 			break;
754 	}
755 
756 	if (!is_complete(t)) {
757 		fprintf(stderr, "Iteration count did not finish!\n");
758 		return -1;
759 	}
760 
761 	return 0;
762 }
763 
prepare_devices(struct loopback_test * t)764 static void prepare_devices(struct loopback_test *t)
765 {
766 	int i;
767 
768 	/*
769 	 * Cancel any running tests on enabled devices. If
770 	 * stop_all option is given, stop test on all devices.
771 	 */
772 	for (i = 0; i < t->device_count; i++)
773 		if (t->stop_all || device_enabled(t, i))
774 			write_sysfs_val(t->devices[i].sysfs_entry, "type", 0);
775 
776 	for (i = 0; i < t->device_count; i++) {
777 		if (!device_enabled(t, i))
778 			continue;
779 
780 		write_sysfs_val(t->devices[i].sysfs_entry, "us_wait",
781 				t->us_wait);
782 
783 		/* Set operation size */
784 		write_sysfs_val(t->devices[i].sysfs_entry, "size", t->size);
785 
786 		/* Set iterations */
787 		write_sysfs_val(t->devices[i].sysfs_entry, "iteration_max",
788 				t->iteration_max);
789 
790 		if (t->use_async) {
791 			write_sysfs_val(t->devices[i].sysfs_entry, "async", 1);
792 			write_sysfs_val(t->devices[i].sysfs_entry,
793 					"timeout", t->async_timeout);
794 			write_sysfs_val(t->devices[i].sysfs_entry,
795 					"outstanding_operations_max",
796 					t->async_outstanding_operations);
797 		} else {
798 			write_sysfs_val(t->devices[i].sysfs_entry, "async", 0);
799 		}
800 	}
801 }
802 
start(struct loopback_test * t)803 static int start(struct loopback_test *t)
804 {
805 	int i;
806 
807 	/* the test starts by writing test_id to the type file. */
808 	for (i = 0; i < t->device_count; i++) {
809 		if (!device_enabled(t, i))
810 			continue;
811 
812 		write_sysfs_val(t->devices[i].sysfs_entry, "type", t->test_id);
813 	}
814 
815 	return 0;
816 }
817 
loopback_run(struct loopback_test * t)818 void loopback_run(struct loopback_test *t)
819 {
820 	int i;
821 	int ret;
822 
823 	for (i = 0; dict[i].name != NULL; i++) {
824 		if (strstr(dict[i].name, t->test_name))
825 			t->test_id = dict[i].type;
826 	}
827 	if (!t->test_id) {
828 		fprintf(stderr, "invalid test %s\n", t->test_name);
829 		usage();
830 		return;
831 	}
832 
833 	prepare_devices(t);
834 
835 	ret = open_poll_files(t);
836 	if (ret)
837 		goto err;
838 
839 	start(t);
840 
841 	ret = wait_for_complete(t);
842 	close_poll_files(t);
843 	if (ret)
844 		goto err;
845 
846 	get_results(t);
847 
848 	log_results(t);
849 
850 	return;
851 
852 err:
853 	printf("Error running test\n");
854 }
855 
sanity_check(struct loopback_test * t)856 static int sanity_check(struct loopback_test *t)
857 {
858 	int i;
859 
860 	if (t->device_count == 0) {
861 		fprintf(stderr, "No loopback devices found\n");
862 		return -1;
863 	}
864 
865 	for (i = 0; i < MAX_NUM_DEVICES; i++) {
866 		if (!device_enabled(t, i))
867 			continue;
868 
869 		if (t->mask && !strcmp(t->devices[i].name, "")) {
870 			fprintf(stderr, "Bad device mask %x\n", (1 << i));
871 			return -1;
872 		}
873 	}
874 
875 	return 0;
876 }
877 
main(int argc,char * argv[])878 int main(int argc, char *argv[])
879 {
880 	int o, ret;
881 	char *sysfs_prefix = "/sys/class/gb_loopback/";
882 	char *debugfs_prefix = "/sys/kernel/debug/gb_loopback/";
883 
884 	memset(&t, 0, sizeof(t));
885 
886 	while ((o = getopt(argc, argv,
887 			   "t:s:i:S:D:m:v::d::r::p::a::l::x::o:O:c:w:z::f::")) != -1) {
888 		switch (o) {
889 		case 't':
890 			snprintf(t.test_name, MAX_STR_LEN, "%s", optarg);
891 			break;
892 		case 's':
893 			t.size = atoi(optarg);
894 			break;
895 		case 'i':
896 			t.iteration_max = atoi(optarg);
897 			break;
898 		case 'S':
899 			snprintf(t.sysfs_prefix, MAX_SYSFS_PREFIX, "%s", optarg);
900 			break;
901 		case 'D':
902 			snprintf(t.debugfs_prefix, MAX_SYSFS_PREFIX, "%s", optarg);
903 			break;
904 		case 'm':
905 			t.mask = atol(optarg);
906 			break;
907 		case 'v':
908 			t.verbose = 1;
909 			break;
910 		case 'd':
911 			t.debug = 1;
912 			break;
913 		case 'r':
914 			t.raw_data_dump = 1;
915 			break;
916 		case 'p':
917 			t.porcelain = 1;
918 			break;
919 		case 'a':
920 			t.aggregate_output = 1;
921 			break;
922 		case 'l':
923 			t.list_devices = 1;
924 			break;
925 		case 'x':
926 			t.use_async = 1;
927 			break;
928 		case 'o':
929 			t.async_timeout = atoi(optarg);
930 			break;
931 		case 'O':
932 			t.poll_timeout.tv_sec = atoi(optarg);
933 			break;
934 		case 'c':
935 			t.async_outstanding_operations = atoi(optarg);
936 			break;
937 		case 'w':
938 			t.us_wait = atoi(optarg);
939 			break;
940 		case 'z':
941 			t.file_output = 1;
942 			break;
943 		case 'f':
944 			t.stop_all = 1;
945 			break;
946 		default:
947 			usage();
948 			return -EINVAL;
949 		}
950 	}
951 
952 	if (!strcmp(t.sysfs_prefix, ""))
953 		snprintf(t.sysfs_prefix, MAX_SYSFS_PREFIX, "%s", sysfs_prefix);
954 
955 	if (!strcmp(t.debugfs_prefix, ""))
956 		snprintf(t.debugfs_prefix, MAX_SYSFS_PREFIX, "%s", debugfs_prefix);
957 
958 	ret = find_loopback_devices(&t);
959 	if (ret)
960 		return ret;
961 	ret = sanity_check(&t);
962 	if (ret)
963 		return ret;
964 
965 	if (t.list_devices) {
966 		show_loopback_devices(&t);
967 		return 0;
968 	}
969 
970 	if (t.test_name[0] == '\0' || t.iteration_max == 0)
971 		usage();
972 
973 	if (t.async_timeout == 0)
974 		t.async_timeout = DEFAULT_ASYNC_TIMEOUT;
975 
976 	loopback_run(&t);
977 
978 	return 0;
979 }
980