Commit 9250c0ee authored by Axel Haslam's avatar Axel Haslam Committed by Greg Kroah-Hartman

greybus: Loopback_test: use poll instead of inotify

Inotify does not handle sysfs events, so use poll instead.

The loopback kernel driver will send a notification when the test is
complete. So, open a poll file descriptor for every enabled device,
and after starting the test, wait for an event from each device.
After all events are received, read the total number of iterations
and make sure the test is complete.

Also, add missing stdint header which was included in inotify.
Signed-off-by: default avatarAxel Haslam <ahaslam@baylibre.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 39c2787b
...@@ -11,7 +11,8 @@ ...@@ -11,7 +11,8 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/inotify.h> #include <stdint.h>
#include <poll.h>
#include <sys/types.h> #include <sys/types.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
...@@ -22,8 +23,7 @@ ...@@ -22,8 +23,7 @@
#define CSV_MAX_LINE 0x1000 #define CSV_MAX_LINE 0x1000
#define SYSFS_MAX_INT 0x20 #define SYSFS_MAX_INT 0x20
#define MAX_STR_LEN 255 #define MAX_STR_LEN 255
#define MAX_TIMEOUT_COUNT 5 #define DEFAULT_POLL_TIMEOUT_SEC 30
#define TIMEOUT_SEC 1
#define DEFAULT_ASYNC_TIMEOUT 200000 #define DEFAULT_ASYNC_TIMEOUT 200000
struct dict { struct dict {
...@@ -71,7 +71,6 @@ struct loopback_device { ...@@ -71,7 +71,6 @@ struct loopback_device {
char name[MAX_SYSFS_PATH]; char name[MAX_SYSFS_PATH];
char sysfs_entry[MAX_SYSFS_PATH]; char sysfs_entry[MAX_SYSFS_PATH];
char debugfs_entry[MAX_SYSFS_PATH]; char debugfs_entry[MAX_SYSFS_PATH];
int inotify_wd;
struct loopback_results results; struct loopback_results results;
}; };
...@@ -86,19 +85,22 @@ struct loopback_test { ...@@ -86,19 +85,22 @@ struct loopback_test {
int aggregate_output; int aggregate_output;
int test_id; int test_id;
int device_count; int device_count;
int inotify_fd;
int list_devices; int list_devices;
int use_async; int use_async;
int async_timeout; int async_timeout;
int poll_timeout;
int async_outstanding_operations; int async_outstanding_operations;
int us_wait; int us_wait;
int file_output; int file_output;
int poll_count;
char test_name[MAX_STR_LEN]; char test_name[MAX_STR_LEN];
char sysfs_prefix[MAX_SYSFS_PATH]; char sysfs_prefix[MAX_SYSFS_PATH];
char debugfs_prefix[MAX_SYSFS_PATH]; char debugfs_prefix[MAX_SYSFS_PATH];
struct loopback_device devices[MAX_NUM_DEVICES]; struct loopback_device devices[MAX_NUM_DEVICES];
struct loopback_results aggregate_results; struct loopback_results aggregate_results;
struct pollfd fds[MAX_NUM_DEVICES];
}; };
struct loopback_test t; struct loopback_test t;
/* Helper macros to calculate the aggregate results for all devices */ /* Helper macros to calculate the aggregate results for all devices */
...@@ -201,6 +203,7 @@ void usage(void) ...@@ -201,6 +203,7 @@ void usage(void)
" -l list found loopback devices and exit\n" " -l list found loopback devices and exit\n"
" -x Async - Enable async transfers\n" " -x Async - Enable async transfers\n"
" -o Async Timeout - Timeout in uSec for async operations\n" " -o Async Timeout - Timeout in uSec for async operations\n"
" -O Poll loop time out in seconds(max time a test is expected to last, default: 30sec)\n"
" -c Max number of outstanding operations for async operations\n" " -c Max number of outstanding operations for async operations\n"
" -w Wait in uSec between operations\n" " -w Wait in uSec between operations\n"
" -z Enable output to a CSV file (incompatible with -p)\n" " -z Enable output to a CSV file (incompatible with -p)\n"
...@@ -638,58 +641,51 @@ int find_loopback_devices(struct loopback_test *t) ...@@ -638,58 +641,51 @@ int find_loopback_devices(struct loopback_test *t)
return ret; return ret;
} }
static int open_poll_files(struct loopback_test *t)
static int register_for_notification(struct loopback_test *t)
{ {
char buf[MAX_SYSFS_PATH]; struct loopback_device *dev;
char buf[MAX_STR_LEN];
char dummy;
int fds_idx = 0;
int i; int i;
t->inotify_fd = inotify_init();
if (t->inotify_fd < 0) {
fprintf(stderr, "inotify_init fail %s\n", strerror(errno));
abort();
}
for (i = 0; i < t->device_count; i++) { for (i = 0; i < t->device_count; i++) {
dev = &t->devices[i];
if (!device_enabled(t, i)) if (!device_enabled(t, i))
continue; continue;
snprintf(buf, sizeof(buf), "%s%s", t->devices[i].sysfs_entry, snprintf(buf, sizeof(buf), "%s%s", dev->sysfs_entry, "iteration_count");
"iteration_count"); t->fds[fds_idx].fd = open(buf, O_RDONLY);
if (t->fds[fds_idx].fd < 0) {
t->devices[i].inotify_wd = inotify_add_watch(t->inotify_fd, fprintf(stderr, "Error opening poll file!\n");
buf, IN_MODIFY); goto err;
if (t->devices[i].inotify_wd < 0) {
fprintf(stderr, "inotify_add_watch %s fail %s\n",
buf, strerror(errno));
close(t->inotify_fd);
abort();
} }
read(t->fds[fds_idx].fd, &dummy, 1);
t->fds[fds_idx].events = POLLERR|POLLPRI;
t->fds[fds_idx].revents = 0;
fds_idx++;
} }
t->poll_count = fds_idx;
return 0; return 0;
err:
for (i = 0; i < fds_idx; i++)
close(t->fds[fds_idx].fd);
return -1;
} }
static int unregister_for_notification(struct loopback_test *t) static int close_poll_files(struct loopback_test *t)
{ {
int i; int i;
int ret = 0; for (i = 0; i < t->poll_count; i++)
close(t->fds[i].fd);
for (i = 0; i < t->device_count; i++) {
if (!device_enabled(t, i))
continue;
ret = inotify_rm_watch(t->inotify_fd, t->devices[i].inotify_wd);
if (ret) {
fprintf(stderr, "inotify_rm_watch error.\n");
return ret;
}
}
close(t->inotify_fd);
return 0; return 0;
} }
static int is_complete(struct loopback_test *t) static int is_complete(struct loopback_test *t)
{ {
int iteration_count; int iteration_count;
...@@ -712,39 +708,38 @@ static int is_complete(struct loopback_test *t) ...@@ -712,39 +708,38 @@ static int is_complete(struct loopback_test *t)
static int wait_for_complete(struct loopback_test *t) static int wait_for_complete(struct loopback_test *t)
{ {
int remaining_timeouts = MAX_TIMEOUT_COUNT; int number_of_events = 0;
char buf[MAX_SYSFS_PATH]; char dummy;
struct timeval timeout;
fd_set read_fds;
int ret; int ret;
int i;
while (1) { while (1) {
/* Wait for change */ ret = poll(t->fds, t->poll_count, DEFAULT_POLL_TIMEOUT_SEC * 1000);
timeout.tv_sec = TIMEOUT_SEC; if (ret == 0) {
timeout.tv_usec = 0; fprintf(stderr, "Poll timmed out!\n");
FD_ZERO(&read_fds);
FD_SET(t->inotify_fd, &read_fds);
ret = select(FD_SETSIZE, &read_fds, NULL, NULL, &timeout);
if (ret < 0) {
fprintf(stderr, "Select error.\n");
return -1; return -1;
} }
/* timeout - test may be finished.*/ if (ret < 0) {
if (!FD_ISSET(t->inotify_fd, &read_fds)) { fprintf(stderr, "Poll Error!\n");
remaining_timeouts--; return -1;
}
if (is_complete(t))
return 0;
if (!remaining_timeouts) { for (i = 0; i < t->poll_count; i++) {
fprintf(stderr, "Too many timeouts\n"); if (t->fds[i].revents & POLLPRI) {
return -1; /* Dummy read to clear the event */
read(t->fds[i].fd, &dummy, 1);
number_of_events++;
} }
} else {
/* read to clear the event */
ret = read(t->inotify_fd, buf, sizeof(buf));
} }
if (number_of_events == t->poll_count)
break;
}
if (!is_complete(t)) {
fprintf(stderr, "Iteration count did not finish!\n");
return -1;
} }
return 0; return 0;
...@@ -820,17 +815,17 @@ void loopback_run(struct loopback_test *t) ...@@ -820,17 +815,17 @@ void loopback_run(struct loopback_test *t)
prepare_devices(t); prepare_devices(t);
ret = register_for_notification(t); ret = open_poll_files(t);
if (ret) if (ret)
goto err; goto err;
start(t); start(t);
sleep(1); ret = wait_for_complete(t);
close_poll_files(t);
wait_for_complete(t); if (ret)
goto err;
unregister_for_notification(t);
get_results(t); get_results(t);
...@@ -875,7 +870,7 @@ int main(int argc, char *argv[]) ...@@ -875,7 +870,7 @@ int main(int argc, char *argv[])
memset(&t, 0, sizeof(t)); memset(&t, 0, sizeof(t));
while ((o = getopt(argc, argv, while ((o = getopt(argc, argv,
"t:s:i:S:D:m:v::d::r::p::a::l::x::o:c:w:")) != -1) { "t:s:i:S:D:m:v::d::r::p::a::l::x::o:c:w:O:")) != -1) {
switch (o) { switch (o) {
case 't': case 't':
snprintf(t.test_name, MAX_STR_LEN, "%s", optarg); snprintf(t.test_name, MAX_STR_LEN, "%s", optarg);
...@@ -919,6 +914,9 @@ int main(int argc, char *argv[]) ...@@ -919,6 +914,9 @@ int main(int argc, char *argv[])
case 'o': case 'o':
t.async_timeout = atoi(optarg); t.async_timeout = atoi(optarg);
break; break;
case 'O':
t.poll_timeout = atoi(optarg);
break;
case 'c': case 'c':
t.async_outstanding_operations = atoi(optarg); t.async_outstanding_operations = atoi(optarg);
break; break;
...@@ -957,6 +955,9 @@ int main(int argc, char *argv[]) ...@@ -957,6 +955,9 @@ int main(int argc, char *argv[])
if (t.async_timeout == 0) if (t.async_timeout == 0)
t.async_timeout = DEFAULT_ASYNC_TIMEOUT; t.async_timeout = DEFAULT_ASYNC_TIMEOUT;
if (t.poll_timeout == 0)
t.poll_timeout = DEFAULT_POLL_TIMEOUT_SEC;
loopback_run(&t); loopback_run(&t);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment