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 
abort(void)170 void abort(void)
171 {
172 	_exit(1);
173 }
174 
usage(void)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 
device_enabled(struct loopback_test * t,int dev_idx)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 
show_loopback_devices(struct loopback_test * t)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 
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 
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 
read_sysfs_int(const char * sys_pfx,const char * node)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 
read_sysfs_float(const char * sys_pfx,const char * node)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 
write_sysfs_val(const char * sys_pfx,const char * node,int val)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 
get_results(struct loopback_test * t)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 
format_output(struct loopback_test * t,struct loopback_results * r,const char * dev_name,char * buf,int buf_len,struct tm * tm)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 
log_results(struct loopback_test * t)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 
is_loopback_device(const char * path,const char * node)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 
find_loopback_devices(struct loopback_test * t)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 
open_poll_files(struct loopback_test * t)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 
close_poll_files(struct loopback_test * t)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 }
is_complete(struct loopback_test * t)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 
stop_tests(struct loopback_test * t)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 
handler(int sig)713 static void handler(int sig) { /* do nothing */  }
714 
wait_for_complete(struct loopback_test * t)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 
prepare_devices(struct loopback_test * t)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 
start(struct loopback_test * t)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 
loopback_run(struct loopback_test * t)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 
sanity_check(struct loopback_test * t)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 
main(int argc,char * argv[])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 }
991