root/drivers/staging/greybus/tools/loopback_test.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. abort
  2. usage
  3. device_enabled
  4. show_loopback_devices
  5. open_sysfs
  6. read_sysfs_int_fd
  7. read_sysfs_float_fd
  8. read_sysfs_int
  9. read_sysfs_float
  10. write_sysfs_val
  11. get_results
  12. format_output
  13. log_results
  14. is_loopback_device
  15. find_loopback_devices
  16. open_poll_files
  17. close_poll_files
  18. is_complete
  19. stop_tests
  20. handler
  21. wait_for_complete
  22. prepare_devices
  23. start
  24. loopback_run
  25. sanity_check
  26. main

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

/* [<][>][^][v][top][bottom][index][help] */