linux/tools/testing/selftests/sparc64/drivers/adi-test.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * selftest for sparc64's privileged ADI driver
   4 *
   5 * Author: Tom Hromatka <tom.hromatka@oracle.com>
   6 */
   7#include <linux/kernel.h>
   8#include <errno.h>
   9#include <fcntl.h>
  10#include <stdarg.h>
  11#include <stdio.h>
  12#include <stdlib.h>
  13#include <string.h>
  14#include <sys/syscall.h>
  15#include <sys/types.h>
  16#include <sys/stat.h>
  17#include <unistd.h>
  18
  19#include "../../kselftest.h"
  20
  21#define DEBUG_LEVEL_1_BIT       (0x0001)
  22#define DEBUG_LEVEL_2_BIT       (0x0002)
  23#define DEBUG_LEVEL_3_BIT       (0x0004)
  24#define DEBUG_LEVEL_4_BIT       (0x0008)
  25#define DEBUG_TIMING_BIT        (0x1000)
  26
  27#ifndef ARRAY_SIZE
  28# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
  29#endif
  30
  31/* bit mask of enabled bits to print */
  32#define DEBUG 0x0001
  33
  34#define DEBUG_PRINT_L1(...)     debug_print(DEBUG_LEVEL_1_BIT, __VA_ARGS__)
  35#define DEBUG_PRINT_L2(...)     debug_print(DEBUG_LEVEL_2_BIT, __VA_ARGS__)
  36#define DEBUG_PRINT_L3(...)     debug_print(DEBUG_LEVEL_3_BIT, __VA_ARGS__)
  37#define DEBUG_PRINT_L4(...)     debug_print(DEBUG_LEVEL_4_BIT, __VA_ARGS__)
  38#define DEBUG_PRINT_T(...)      debug_print(DEBUG_TIMING_BIT, __VA_ARGS__)
  39
  40static void debug_print(int level, const char *s, ...)
  41{
  42        va_list args;
  43
  44        va_start(args, s);
  45
  46        if (DEBUG & level)
  47                vfprintf(stdout, s, args);
  48        va_end(args);
  49}
  50
  51#ifndef min
  52#define min(x, y) ((x) < (y) ? x : y)
  53#endif
  54
  55#define RETURN_FROM_TEST(_ret) \
  56        do { \
  57                DEBUG_PRINT_L1( \
  58                        "\tTest %s returned %d\n", __func__, _ret); \
  59                return _ret; \
  60        } while (0)
  61
  62#define ADI_BLKSZ       64
  63#define ADI_MAX_VERSION 15
  64
  65#define TEST_STEP_FAILURE(_ret) \
  66        do { \
  67                fprintf(stderr, "\tTest step failure: %d at %s:%d\n", \
  68                        _ret, __func__, __LINE__); \
  69                goto out; \
  70        } while (0)
  71
  72#define RDTICK(_x) \
  73        asm volatile(" rd %%tick, %0\n" : "=r" (_x))
  74
  75static int random_version(void)
  76{
  77        long tick;
  78
  79        RDTICK(tick);
  80
  81        return tick % (ADI_MAX_VERSION + 1);
  82}
  83
  84#define MAX_RANGES_SUPPORTED    5
  85static const char system_ram_str[] = "System RAM\n";
  86static int range_count;
  87static unsigned long long int start_addr[MAX_RANGES_SUPPORTED];
  88static unsigned long long int   end_addr[MAX_RANGES_SUPPORTED];
  89
  90struct stats {
  91        char            name[16];
  92        unsigned long   total;
  93        unsigned long   count;
  94        unsigned long   bytes;
  95};
  96
  97static struct stats read_stats = {
  98        .name = "read", .total = 0, .count = 0, .bytes = 0};
  99static struct stats pread_stats = {
 100        .name = "pread", .total = 0, .count = 0, .bytes = 0};
 101static struct stats write_stats = {
 102        .name = "write", .total = 0, .count = 0, .bytes = 0};
 103static struct stats pwrite_stats = {
 104        .name = "pwrite", .total = 0, .count = 0, .bytes = 0};
 105static struct stats seek_stats = {
 106        .name = "seek", .total = 0, .count = 0, .bytes = 0};
 107
 108static void update_stats(struct stats * const ustats,
 109                         unsigned long measurement, unsigned long bytes)
 110{
 111        ustats->total += measurement;
 112        ustats->bytes += bytes;
 113        ustats->count++;
 114}
 115
 116static void print_ustats(const struct stats * const ustats)
 117{
 118        DEBUG_PRINT_L1("%s\t%7d\t%7.0f\t%7.0f\n",
 119                       ustats->name, ustats->count,
 120                       (float)ustats->total / (float)ustats->count,
 121                       (float)ustats->bytes / (float)ustats->count);
 122}
 123
 124static void print_stats(void)
 125{
 126        DEBUG_PRINT_L1("\nSyscall\tCall\tAvgTime\tAvgSize\n"
 127                       "\tCount\t(ticks)\t(bytes)\n"
 128                       "-------------------------------\n");
 129
 130        print_ustats(&read_stats);
 131        print_ustats(&pread_stats);
 132        print_ustats(&write_stats);
 133        print_ustats(&pwrite_stats);
 134        print_ustats(&seek_stats);
 135}
 136
 137static int build_memory_map(void)
 138{
 139        char line[256];
 140        FILE *fp;
 141        int i;
 142
 143        range_count = 0;
 144
 145        fp = fopen("/proc/iomem", "r");
 146        if (!fp) {
 147                fprintf(stderr, "/proc/iomem: error %d: %s\n",
 148                        errno, strerror(errno));
 149                return -errno;
 150        }
 151
 152        while (fgets(line, sizeof(line), fp) != 0) {
 153                if (strstr(line, system_ram_str)) {
 154                        char *dash, *end_ptr;
 155
 156                        /* Given a line like this:
 157                         * d0400000-10ffaffff : System RAM
 158                         * replace the "-" with a space
 159                         */
 160                        dash = strstr(line, "-");
 161                        dash[0] = 0x20;
 162
 163                        start_addr[range_count] = strtoull(line, &end_ptr, 16);
 164                        end_addr[range_count] = strtoull(end_ptr, NULL, 16);
 165                        range_count++;
 166                }
 167        }
 168
 169        fclose(fp);
 170
 171        DEBUG_PRINT_L1("RAM Ranges\n");
 172        for (i = 0; i < range_count; i++)
 173                DEBUG_PRINT_L1("\trange %d: 0x%llx\t- 0x%llx\n",
 174                               i, start_addr[i], end_addr[i]);
 175
 176        if (range_count == 0) {
 177                fprintf(stderr, "No valid address ranges found.  Error.\n");
 178                return -1;
 179        }
 180
 181        return 0;
 182}
 183
 184static int read_adi(int fd, unsigned char *buf, int buf_sz)
 185{
 186        int ret, bytes_read = 0;
 187        long start, end, elapsed_time = 0;
 188
 189        do {
 190                RDTICK(start);
 191                ret = read(fd, buf + bytes_read, buf_sz - bytes_read);
 192                RDTICK(end);
 193                if (ret < 0)
 194                        return -errno;
 195
 196                elapsed_time += end - start;
 197                update_stats(&read_stats, elapsed_time, buf_sz);
 198                bytes_read += ret;
 199
 200        } while (bytes_read < buf_sz);
 201
 202        DEBUG_PRINT_T("\tread elapsed timed = %ld\n", elapsed_time);
 203        DEBUG_PRINT_L3("\tRead  %d bytes\n", bytes_read);
 204
 205        return bytes_read;
 206}
 207
 208static int pread_adi(int fd, unsigned char *buf,
 209                     int buf_sz, unsigned long offset)
 210{
 211        int ret, i, bytes_read = 0;
 212        unsigned long cur_offset;
 213        long start, end, elapsed_time = 0;
 214
 215        cur_offset = offset;
 216        do {
 217                RDTICK(start);
 218                ret = pread(fd, buf + bytes_read, buf_sz - bytes_read,
 219                            cur_offset);
 220                RDTICK(end);
 221                if (ret < 0)
 222                        return -errno;
 223
 224                elapsed_time += end - start;
 225                update_stats(&pread_stats, elapsed_time, buf_sz);
 226                bytes_read += ret;
 227                cur_offset += ret;
 228
 229        } while (bytes_read < buf_sz);
 230
 231        DEBUG_PRINT_T("\tpread elapsed timed = %ld\n", elapsed_time);
 232        DEBUG_PRINT_L3("\tRead  %d bytes starting at offset 0x%lx\n",
 233                       bytes_read, offset);
 234        for (i = 0; i < bytes_read; i++)
 235                DEBUG_PRINT_L4("\t\t0x%lx\t%d\n", offset + i, buf[i]);
 236
 237        return bytes_read;
 238}
 239
 240static int write_adi(int fd, const unsigned char * const buf, int buf_sz)
 241{
 242        int ret, bytes_written = 0;
 243        long start, end, elapsed_time = 0;
 244
 245        do {
 246                RDTICK(start);
 247                ret = write(fd, buf + bytes_written, buf_sz - bytes_written);
 248                RDTICK(end);
 249                if (ret < 0)
 250                        return -errno;
 251
 252                elapsed_time += (end - start);
 253                update_stats(&write_stats, elapsed_time, buf_sz);
 254                bytes_written += ret;
 255        } while (bytes_written < buf_sz);
 256
 257        DEBUG_PRINT_T("\twrite elapsed timed = %ld\n", elapsed_time);
 258        DEBUG_PRINT_L3("\tWrote %d of %d bytes\n", bytes_written, buf_sz);
 259
 260        return bytes_written;
 261}
 262
 263static int pwrite_adi(int fd, const unsigned char * const buf,
 264                      int buf_sz, unsigned long offset)
 265{
 266        int ret, bytes_written = 0;
 267        unsigned long cur_offset;
 268        long start, end, elapsed_time = 0;
 269
 270        cur_offset = offset;
 271
 272        do {
 273                RDTICK(start);
 274                ret = pwrite(fd, buf + bytes_written,
 275                             buf_sz - bytes_written, cur_offset);
 276                RDTICK(end);
 277                if (ret < 0) {
 278                        fprintf(stderr, "pwrite(): error %d: %s\n",
 279                                errno, strerror(errno));
 280                        return -errno;
 281                }
 282
 283                elapsed_time += (end - start);
 284                update_stats(&pwrite_stats, elapsed_time, buf_sz);
 285                bytes_written += ret;
 286                cur_offset += ret;
 287
 288        } while (bytes_written < buf_sz);
 289
 290        DEBUG_PRINT_T("\tpwrite elapsed timed = %ld\n", elapsed_time);
 291        DEBUG_PRINT_L3("\tWrote %d of %d bytes starting at address 0x%lx\n",
 292                       bytes_written, buf_sz, offset);
 293
 294        return bytes_written;
 295}
 296
 297static off_t seek_adi(int fd, off_t offset, int whence)
 298{
 299        long start, end;
 300        off_t ret;
 301
 302        RDTICK(start);
 303        ret = lseek(fd, offset, whence);
 304        RDTICK(end);
 305        DEBUG_PRINT_L2("\tlseek ret = 0x%llx\n", ret);
 306        if (ret < 0)
 307                goto out;
 308
 309        DEBUG_PRINT_T("\tlseek elapsed timed = %ld\n", end - start);
 310        update_stats(&seek_stats, end - start, 0);
 311
 312out:
 313        (void)lseek(fd, 0, SEEK_END);
 314        return ret;
 315}
 316
 317static int test0_prpw_aligned_1byte(int fd)
 318{
 319        /* somewhat arbitrarily chosen address */
 320        unsigned long paddr =
 321                (end_addr[range_count - 1] - 0x1000) & ~(ADI_BLKSZ - 1);
 322        unsigned char version[1], expected_version;
 323        loff_t offset;
 324        int ret;
 325
 326        version[0] = random_version();
 327        expected_version = version[0];
 328
 329        offset = paddr / ADI_BLKSZ;
 330
 331        ret = pwrite_adi(fd, version, sizeof(version), offset);
 332        if (ret != sizeof(version))
 333                TEST_STEP_FAILURE(ret);
 334
 335        ret = pread_adi(fd, version, sizeof(version), offset);
 336        if (ret != sizeof(version))
 337                TEST_STEP_FAILURE(ret);
 338
 339        if (expected_version != version[0]) {
 340                DEBUG_PRINT_L2("\tExpected version %d but read version %d\n",
 341                               expected_version, version[0]);
 342                TEST_STEP_FAILURE(-expected_version);
 343        }
 344
 345        ret = 0;
 346out:
 347        RETURN_FROM_TEST(ret);
 348}
 349
 350#define TEST1_VERSION_SZ        4096
 351static int test1_prpw_aligned_4096bytes(int fd)
 352{
 353        /* somewhat arbitrarily chosen address */
 354        unsigned long paddr =
 355                (end_addr[range_count - 1] - 0x6000) & ~(ADI_BLKSZ - 1);
 356        unsigned char version[TEST1_VERSION_SZ],
 357                expected_version[TEST1_VERSION_SZ];
 358        loff_t offset;
 359        int ret, i;
 360
 361        for (i = 0; i < TEST1_VERSION_SZ; i++) {
 362                version[i] = random_version();
 363                expected_version[i] = version[i];
 364        }
 365
 366        offset = paddr / ADI_BLKSZ;
 367
 368        ret = pwrite_adi(fd, version, sizeof(version), offset);
 369        if (ret != sizeof(version))
 370                TEST_STEP_FAILURE(ret);
 371
 372        ret = pread_adi(fd, version, sizeof(version), offset);
 373        if (ret != sizeof(version))
 374                TEST_STEP_FAILURE(ret);
 375
 376        for (i = 0; i < TEST1_VERSION_SZ; i++) {
 377                if (expected_version[i] != version[i]) {
 378                        DEBUG_PRINT_L2(
 379                                "\tExpected version %d but read version %d\n",
 380                                expected_version, version[0]);
 381                        TEST_STEP_FAILURE(-expected_version[i]);
 382                }
 383        }
 384
 385        ret = 0;
 386out:
 387        RETURN_FROM_TEST(ret);
 388}
 389
 390#define TEST2_VERSION_SZ        10327
 391static int test2_prpw_aligned_10327bytes(int fd)
 392{
 393        /* somewhat arbitrarily chosen address */
 394        unsigned long paddr =
 395                (start_addr[0] + 0x6000) & ~(ADI_BLKSZ - 1);
 396        unsigned char version[TEST2_VERSION_SZ],
 397                expected_version[TEST2_VERSION_SZ];
 398        loff_t offset;
 399        int ret, i;
 400
 401        for (i = 0; i < TEST2_VERSION_SZ; i++) {
 402                version[i] = random_version();
 403                expected_version[i] = version[i];
 404        }
 405
 406        offset = paddr / ADI_BLKSZ;
 407
 408        ret = pwrite_adi(fd, version, sizeof(version), offset);
 409        if (ret != sizeof(version))
 410                TEST_STEP_FAILURE(ret);
 411
 412        ret = pread_adi(fd, version, sizeof(version), offset);
 413        if (ret != sizeof(version))
 414                TEST_STEP_FAILURE(ret);
 415
 416        for (i = 0; i < TEST2_VERSION_SZ; i++) {
 417                if (expected_version[i] != version[i]) {
 418                        DEBUG_PRINT_L2(
 419                                "\tExpected version %d but read version %d\n",
 420                                expected_version, version[0]);
 421                        TEST_STEP_FAILURE(-expected_version[i]);
 422                }
 423        }
 424
 425        ret = 0;
 426out:
 427        RETURN_FROM_TEST(ret);
 428}
 429
 430#define TEST3_VERSION_SZ        12541
 431static int test3_prpw_unaligned_12541bytes(int fd)
 432{
 433        /* somewhat arbitrarily chosen address */
 434        unsigned long paddr =
 435                ((start_addr[0] + 0xC000) & ~(ADI_BLKSZ - 1)) + 17;
 436        unsigned char version[TEST3_VERSION_SZ],
 437                expected_version[TEST3_VERSION_SZ];
 438        loff_t offset;
 439        int ret, i;
 440
 441        for (i = 0; i < TEST3_VERSION_SZ; i++) {
 442                version[i] = random_version();
 443                expected_version[i] = version[i];
 444        }
 445
 446        offset = paddr / ADI_BLKSZ;
 447
 448        ret = pwrite_adi(fd, version, sizeof(version), offset);
 449        if (ret != sizeof(version))
 450                TEST_STEP_FAILURE(ret);
 451
 452        ret = pread_adi(fd, version, sizeof(version), offset);
 453        if (ret != sizeof(version))
 454                TEST_STEP_FAILURE(ret);
 455
 456        for (i = 0; i < TEST3_VERSION_SZ; i++) {
 457                if (expected_version[i] != version[i]) {
 458                        DEBUG_PRINT_L2(
 459                                "\tExpected version %d but read version %d\n",
 460                                expected_version, version[0]);
 461                        TEST_STEP_FAILURE(-expected_version[i]);
 462                }
 463        }
 464
 465        ret = 0;
 466out:
 467        RETURN_FROM_TEST(ret);
 468}
 469
 470static int test4_lseek(int fd)
 471{
 472#define OFFSET_ADD      (0x100)
 473#define OFFSET_SUBTRACT (0xFFFFFFF000000000)
 474
 475        off_t offset_out, offset_in;
 476        int ret;
 477
 478
 479        offset_in = 0x123456789abcdef0;
 480        offset_out = seek_adi(fd, offset_in, SEEK_SET);
 481        if (offset_out != offset_in) {
 482                ret = -1;
 483                TEST_STEP_FAILURE(ret);
 484        }
 485
 486        /* seek to the current offset.  this should return EINVAL */
 487        offset_out = seek_adi(fd, offset_in, SEEK_SET);
 488        if (offset_out < 0 && errno == EINVAL)
 489                DEBUG_PRINT_L2(
 490                        "\tSEEK_SET failed as designed. Not an error\n");
 491        else {
 492                ret = -2;
 493                TEST_STEP_FAILURE(ret);
 494        }
 495
 496        offset_out = seek_adi(fd, 0, SEEK_CUR);
 497        if (offset_out != offset_in) {
 498                ret = -3;
 499                TEST_STEP_FAILURE(ret);
 500        }
 501
 502        offset_out = seek_adi(fd, OFFSET_ADD, SEEK_CUR);
 503        if (offset_out != (offset_in + OFFSET_ADD)) {
 504                ret = -4;
 505                TEST_STEP_FAILURE(ret);
 506        }
 507
 508        offset_out = seek_adi(fd, OFFSET_SUBTRACT, SEEK_CUR);
 509        if (offset_out != (offset_in + OFFSET_ADD + OFFSET_SUBTRACT)) {
 510                ret = -5;
 511                TEST_STEP_FAILURE(ret);
 512        }
 513
 514        ret = 0;
 515out:
 516        RETURN_FROM_TEST(ret);
 517}
 518
 519static int test5_rw_aligned_1byte(int fd)
 520{
 521        /* somewhat arbitrarily chosen address */
 522        unsigned long paddr =
 523                (end_addr[range_count - 1] - 0xF000) & ~(ADI_BLKSZ - 1);
 524        unsigned char version, expected_version;
 525        loff_t offset;
 526        off_t oret;
 527        int ret;
 528
 529        offset = paddr / ADI_BLKSZ;
 530        version = expected_version = random_version();
 531
 532        oret = seek_adi(fd, offset, SEEK_SET);
 533        if (oret != offset) {
 534                ret = -1;
 535                TEST_STEP_FAILURE(ret);
 536        }
 537
 538        ret = write_adi(fd, &version, sizeof(version));
 539        if (ret != sizeof(version))
 540                TEST_STEP_FAILURE(ret);
 541
 542        oret = seek_adi(fd, offset, SEEK_SET);
 543        if (oret != offset) {
 544                ret = -1;
 545                TEST_STEP_FAILURE(ret);
 546        }
 547
 548        ret = read_adi(fd, &version, sizeof(version));
 549        if (ret != sizeof(version))
 550                TEST_STEP_FAILURE(ret);
 551
 552        if (expected_version != version) {
 553                DEBUG_PRINT_L2("\tExpected version %d but read version %d\n",
 554                               expected_version, version);
 555                TEST_STEP_FAILURE(-expected_version);
 556        }
 557
 558        ret = 0;
 559out:
 560        RETURN_FROM_TEST(ret);
 561}
 562
 563#define TEST6_VERSION_SZ        9434
 564static int test6_rw_aligned_9434bytes(int fd)
 565{
 566        /* somewhat arbitrarily chosen address */
 567        unsigned long paddr =
 568                (end_addr[range_count - 1] - 0x5F000) & ~(ADI_BLKSZ - 1);
 569        unsigned char version[TEST6_VERSION_SZ],
 570                      expected_version[TEST6_VERSION_SZ];
 571        loff_t offset;
 572        off_t oret;
 573        int ret, i;
 574
 575        offset = paddr / ADI_BLKSZ;
 576        for (i = 0; i < TEST6_VERSION_SZ; i++)
 577                version[i] = expected_version[i] = random_version();
 578
 579        oret = seek_adi(fd, offset, SEEK_SET);
 580        if (oret != offset) {
 581                ret = -1;
 582                TEST_STEP_FAILURE(ret);
 583        }
 584
 585        ret = write_adi(fd, version, sizeof(version));
 586        if (ret != sizeof(version))
 587                TEST_STEP_FAILURE(ret);
 588
 589        memset(version, 0, TEST6_VERSION_SZ);
 590
 591        oret = seek_adi(fd, offset, SEEK_SET);
 592        if (oret != offset) {
 593                ret = -1;
 594                TEST_STEP_FAILURE(ret);
 595        }
 596
 597        ret = read_adi(fd, version, sizeof(version));
 598        if (ret != sizeof(version))
 599                TEST_STEP_FAILURE(ret);
 600
 601        for (i = 0; i < TEST6_VERSION_SZ; i++) {
 602                if (expected_version[i] != version[i]) {
 603                        DEBUG_PRINT_L2(
 604                                "\tExpected version %d but read version %d\n",
 605                                expected_version[i], version[i]);
 606                        TEST_STEP_FAILURE(-expected_version[i]);
 607                }
 608        }
 609
 610        ret = 0;
 611out:
 612        RETURN_FROM_TEST(ret);
 613}
 614
 615#define TEST7_VERSION_SZ        14963
 616static int test7_rw_aligned_14963bytes(int fd)
 617{
 618        /* somewhat arbitrarily chosen address */
 619        unsigned long paddr =
 620          ((start_addr[range_count - 1] + 0xF000) & ~(ADI_BLKSZ - 1)) + 39;
 621        unsigned char version[TEST7_VERSION_SZ],
 622                      expected_version[TEST7_VERSION_SZ];
 623        loff_t offset;
 624        off_t oret;
 625        int ret, i;
 626
 627        offset = paddr / ADI_BLKSZ;
 628        for (i = 0; i < TEST7_VERSION_SZ; i++) {
 629                version[i] = random_version();
 630                expected_version[i] = version[i];
 631        }
 632
 633        oret = seek_adi(fd, offset, SEEK_SET);
 634        if (oret != offset) {
 635                ret = -1;
 636                TEST_STEP_FAILURE(ret);
 637        }
 638
 639        ret = write_adi(fd, version, sizeof(version));
 640        if (ret != sizeof(version))
 641                TEST_STEP_FAILURE(ret);
 642
 643        memset(version, 0, TEST7_VERSION_SZ);
 644
 645        oret = seek_adi(fd, offset, SEEK_SET);
 646        if (oret != offset) {
 647                ret = -1;
 648                TEST_STEP_FAILURE(ret);
 649        }
 650
 651        ret = read_adi(fd, version, sizeof(version));
 652        if (ret != sizeof(version))
 653                TEST_STEP_FAILURE(ret);
 654
 655        for (i = 0; i < TEST7_VERSION_SZ; i++) {
 656                if (expected_version[i] != version[i]) {
 657                        DEBUG_PRINT_L2(
 658                                "\tExpected version %d but read version %d\n",
 659                                expected_version[i], version[i]);
 660                        TEST_STEP_FAILURE(-expected_version[i]);
 661                }
 662
 663                paddr += ADI_BLKSZ;
 664        }
 665
 666        ret = 0;
 667out:
 668        RETURN_FROM_TEST(ret);
 669}
 670
 671static int (*tests[])(int fd) = {
 672        test0_prpw_aligned_1byte,
 673        test1_prpw_aligned_4096bytes,
 674        test2_prpw_aligned_10327bytes,
 675        test3_prpw_unaligned_12541bytes,
 676        test4_lseek,
 677        test5_rw_aligned_1byte,
 678        test6_rw_aligned_9434bytes,
 679        test7_rw_aligned_14963bytes,
 680};
 681#define TEST_COUNT      ARRAY_SIZE(tests)
 682
 683int main(int argc, char *argv[])
 684{
 685        int fd, ret, test;
 686
 687        ret = build_memory_map();
 688        if (ret < 0)
 689                return ret;
 690
 691        fd = open("/dev/adi", O_RDWR);
 692        if (fd < 0) {
 693                fprintf(stderr, "open: error %d: %s\n",
 694                        errno, strerror(errno));
 695                return -errno;
 696        }
 697
 698        for (test = 0; test < TEST_COUNT; test++) {
 699                DEBUG_PRINT_L1("Running test #%d\n", test);
 700
 701                ret = (*tests[test])(fd);
 702                if (ret != 0)
 703                        ksft_test_result_fail("Test #%d failed: error %d\n",
 704                                              test, ret);
 705                else
 706                        ksft_test_result_pass("Test #%d passed\n", test);
 707        }
 708
 709        print_stats();
 710        close(fd);
 711
 712        if (ksft_get_fail_cnt() > 0)
 713                ksft_exit_fail();
 714        else
 715                ksft_exit_pass();
 716
 717        /* it's impossible to get here, but the compiler throws a warning
 718         * about control reaching the end of non-void function.  bah.
 719         */
 720        return 0;
 721}
 722