/* * GSP RPC Client Test/Validation Harness * Tests message encoding/decoding, RPC structure validation */ #define pr_fmt(fmt) "vgsp-rpc-test: " fmt #include #include #include #include #include #include "../include/gsp_rpc_client.h" #include "../include/nvidia-vgpu-vfio.h" #define TEST_PASS 0 #define TEST_FAIL -1 static int test_count = 0; static int pass_count = 0; static int fail_count = 0; #define TEST_ASSERT(cond, msg) \ do { \ test_count++; \ if (cond) { \ pass_count++; \ pr_info("PASS: %s\n", msg); \ } else { \ fail_count++; \ pr_err("FAIL: %s\n", msg); \ } \ } while (0) #define TEST_ASSERT_EQ(a, b, msg) \ TEST_ASSERT((a) == (b), msg " (expected " #b ", got " #a ")") /* ============================================================ * Structure Size/Alignment Tests * ============================================================ */ static int test_structure_sizes(void) { pr_info("=== Testing Structure Sizes ===\n"); TEST_ASSERT_EQ(sizeof(struct gsp_rpc_msg), 72, "gsp_rpc_msg size"); TEST_ASSERT_EQ(sizeof(struct gsp_rpc_response), 64, "gsp_rpc_response size"); TEST_ASSERT_EQ(sizeof(struct gsp_alloc_req), 40, "gsp_alloc_req size"); TEST_ASSERT_EQ(sizeof(struct gsp_alloc_rsp), 24, "gsp_alloc_rsp size"); TEST_ASSERT_EQ(sizeof(struct gsp_map_req), 48, "gsp_map_req size"); TEST_ASSERT_EQ(sizeof(struct gsp_map_rsp), 8, "gsp_map_rsp size"); TEST_ASSERT_EQ(sizeof(struct gsp_pin_req), 40, "gsp_pin_req size"); TEST_ASSERT_EQ(sizeof(struct gsp_pin_rsp), 16, "gsp_pin_rsp size"); TEST_ASSERT_EQ(sizeof(struct gsp_sched_req), 40, "gsp_sched_req size"); TEST_ASSERT_EQ(sizeof(struct gsp_bar_trap_req), 32, "gsp_bar_trap_req size"); TEST_ASSERT_EQ(sizeof(struct gsp_bar_trap_rsp), 16, "gsp_bar_trap_rsp size"); TEST_ASSERT_EQ(sizeof(struct gsp_migrate_req), 56, "gsp_migrate_req size"); TEST_ASSERT_EQ(sizeof(struct gsp_migrate_rsp), 16, "gsp_migrate_rsp size"); return TEST_PASS; } static int test_structure_alignment(void) { pr_info("=== Testing Structure Alignment ===\n"); TEST_ASSERT_EQ(__alignof__(struct gsp_rpc_msg), 8, "gsp_rpc_msg alignment"); TEST_ASSERT_EQ(__alignof__(struct gsp_rpc_response), 8, "gsp_rpc_response alignment"); TEST_ASSERT_EQ(__alignof__(struct gsp_alloc_req), 8, "gsp_alloc_req alignment"); TEST_ASSERT_EQ(__alignof__(struct gsp_map_req), 8, "gsp_map_req alignment"); TEST_ASSERT_EQ(__alignof__(struct gsp_pin_req), 8, "gsp_pin_req alignment"); TEST_ASSERT_EQ(__alignof__(struct gsp_sched_req), 8, "gsp_sched_req alignment"); TEST_ASSERT_EQ(__alignof__(struct gsp_bar_trap_req), 8, "gsp_bar_trap_req alignment"); TEST_ASSERT_EQ(__alignof__(struct gsp_migrate_req), 8, "gsp_migrate_req alignment"); return TEST_PASS; } /* ============================================================ * Message Encoding/Decoding Tests * ============================================================ */ static int test_rpc_msg_encoding(void) { struct gsp_rpc_msg msg = {0}; struct gsp_alloc_req *alloc_req = (struct gsp_alloc_req *)msg.payload; pr_info("=== Testing RPC Message Encoding ===\n"); /* Test ALLOC message encoding */ msg.type = cpu_to_le32(GSP_RPC_ALLOC); msg.subcmd = cpu_to_le32(GSP_ALLOC_SUBCMD_DEFAULT); msg.seq_id = cpu_to_le32(0x12345678); msg.flags = cpu_to_le32(0x00000001); alloc_req->size = cpu_to_le64(0x100000); alloc_req->alignment = cpu_to_le64(0x1000); alloc_req->mem_type = cpu_to_le32(0x2); alloc_req->flags = cpu_to_le32(0x3); alloc_req->addr_hint = cpu_to_le64(0x0); alloc_req->pid = cpu_to_le32(0x456); alloc_req->reserved = 0; TEST_ASSERT_EQ(le32_to_cpu(msg.type), GSP_RPC_ALLOC, "RPC type field"); TEST_ASSERT_EQ(le32_to_cpu(msg.subcmd), GSP_ALLOC_SUBCMD_DEFAULT, "RPC subcmd field"); TEST_ASSERT_EQ(le32_to_cpu(msg.seq_id), 0x12345678, "RPC seq_id field"); TEST_ASSERT_EQ(le32_to_cpu(msg.flags), 0x00000001, "RPC flags field"); TEST_ASSERT_EQ(le64_to_cpu(alloc_req->size), 0x100000, "ALLOC size field"); TEST_ASSERT_EQ(le64_to_cpu(alloc_req->alignment), 0x1000, "ALLOC alignment field"); TEST_ASSERT_EQ(le32_to_cpu(alloc_req->mem_type), 0x2, "ALLOC mem_type field"); TEST_ASSERT_EQ(le32_to_cpu(alloc_req->flags), 0x3, "ALLOC flags field"); TEST_ASSERT_EQ(le64_to_cpu(alloc_req->addr_hint), 0x0, "ALLOC addr_hint field"); TEST_ASSERT_EQ(le32_to_cpu(alloc_req->pid), 0x456, "ALLOC pid field"); return TEST_PASS; } static int test_map_msg_encoding(void) { struct gsp_rpc_msg msg = {0}; struct gsp_map_req *map_req = (struct gsp_map_req *)msg.payload; pr_info("=== Testing MAP Message Encoding ===\n"); msg.type = cpu_to_le32(GSP_RPC_MAP); msg.subcmd = cpu_to_le32(0); msg.seq_id = cpu_to_le32(0xABCDEF00); map_req->handle = cpu_to_le64(0xDEADBEEF); map_req->gpu_va = cpu_to_le64(0x80000000); map_req->size = cpu_to_le64(0x200000); map_req->prot = cpu_to_le32(0x7); map_req->flags = cpu_to_le32(0x1); map_req->offset = cpu_to_le64(0x0); map_req->reserved = 0; TEST_ASSERT_EQ(le32_to_cpu(msg.type), GSP_RPC_MAP, "MAP RPC type"); TEST_ASSERT_EQ(le64_to_cpu(map_req->handle), 0xDEADBEEF, "MAP handle"); TEST_ASSERT_EQ(le64_to_cpu(map_req->gpu_va), 0x80000000, "MAP gpu_va"); TEST_ASSERT_EQ(le64_to_cpu(map_req->size), 0x200000, "MAP size"); TEST_ASSERT_EQ(le32_to_cpu(map_req->prot), 0x7, "MAP prot"); TEST_ASSERT_EQ(le32_to_cpu(map_req->flags), 0x1, "MAP flags"); TEST_ASSERT_EQ(le64_to_cpu(map_req->offset), 0x0, "MAP offset"); return TEST_PASS; } static int test_pin_msg_encoding(void) { struct gsp_rpc_msg msg = {0}; struct gsp_pin_req *pin_req = (struct gsp_pin_req *)msg.payload; pr_info("=== Testing PIN Message Encoding ===\n"); msg.type = cpu_to_le32(GSP_RPC_PIN); msg.subcmd = cpu_to_le32(GSP_PIN_SUBCMD_DEFAULT); pin_req->handle = cpu_to_le64(0xCAFEBABE); pin_req->offset = cpu_to_le64(0x1000); pin_req->size = cpu_to_le64(0x10000); pin_req->flags = cpu_to_le32(0x3); pin_req->reserved[0] = 0; pin_req->reserved[1] = 0; TEST_ASSERT_EQ(le32_to_cpu(msg.type), GSP_RPC_PIN, "PIN RPC type"); TEST_ASSERT_EQ(le32_to_cpu(msg.subcmd), GSP_PIN_SUBCMD_DEFAULT, "PIN subcmd"); TEST_ASSERT_EQ(le64_to_cpu(pin_req->handle), 0xCAFEBABE, "PIN handle"); TEST_ASSERT_EQ(le64_to_cpu(pin_req->offset), 0x1000, "PIN offset"); TEST_ASSERT_EQ(le64_to_cpu(pin_req->size), 0x10000, "PIN size"); TEST_ASSERT_EQ(le32_to_cpu(pin_req->flags), 0x3, "PIN flags"); return TEST_PASS; } static int test_sched_msg_encoding(void) { struct gsp_rpc_msg msg = {0}; struct gsp_sched_req *sched_req = (struct gsp_sched_req *)msg.payload; pr_info("=== Testing SCHEDULE Message Encoding ===\n"); msg.type = cpu_to_le32(GSP_RPC_SCHEDULE); msg.subcmd = cpu_to_le32(GSP_SCHED_SUBCMD_DEFAULT); sched_req->work_handle = cpu_to_le64(0x11111111); sched_req->callback = cpu_to_le64(0x22222222); sched_req->arg = cpu_to_le64(0x33333333); sched_req->priority = cpu_to_le32(0x5); sched_req->flags = cpu_to_le32(0x0); sched_req->reserved[0] = 0; sched_req->reserved[1] = 0; TEST_ASSERT_EQ(le32_to_cpu(msg.type), GSP_RPC_SCHEDULE, "SCHED RPC type"); TEST_ASSERT_EQ(le64_to_cpu(sched_req->work_handle), 0x11111111, "SCHED work_handle"); TEST_ASSERT_EQ(le64_to_cpu(sched_req->callback), 0x22222222, "SCHED callback"); TEST_ASSERT_EQ(le64_to_cpu(sched_req->arg), 0x33333333, "SCHED arg"); TEST_ASSERT_EQ(le32_to_cpu(sched_req->priority), 0x5, "SCHED priority"); return TEST_PASS; } static int test_bar_trap_msg_encoding(void) { struct gsp_rpc_msg msg = {0}; struct gsp_bar_trap_req *bar_req = (struct gsp_bar_trap_req *)msg.payload; pr_info("=== Testing BAR_TRAP Message Encoding ===\n"); msg.type = cpu_to_le32(GSP_RPC_BAR_TRAP); msg.subcmd = cpu_to_le32(GSP_BAR_TRAP_SUBCMD_DEFAULT); bar_req->bar_addr = cpu_to_le64(0x00100000); bar_req->access_type = cpu_to_le32(0x1); bar_req->size = cpu_to_le32(0x4); bar_req->value = cpu_to_le64(0xDEADBEEF); bar_req->bar_num = cpu_to_le32(0x1); TEST_ASSERT_EQ(le32_to_cpu(msg.type), GSP_RPC_BAR_TRAP, "BAR_TRAP RPC type"); TEST_ASSERT_EQ(le64_to_cpu(bar_req->bar_addr), 0x00100000, "BAR_TRAP bar_addr"); TEST_ASSERT_EQ(le32_to_cpu(bar_req->access_type), 0x1, "BAR_TRAP access_type"); TEST_ASSERT_EQ(le32_to_cpu(bar_req->size), 0x4, "BAR_TRAP size"); TEST_ASSERT_EQ(le64_to_cpu(bar_req->value), 0xDEADBEEF, "BAR_TRAP value"); TEST_ASSERT_EQ(le32_to_cpu(bar_req->bar_num), 0x1, "BAR_TRAP bar_num"); return TEST_PASS; } static int test_migrate_msg_encoding(void) { struct gsp_rpc_msg msg = {0}; struct gsp_migrate_req *mig_req = (struct gsp_migrate_req *)msg.payload; pr_info("=== Testing MIGRATE Message Encoding ===\n"); msg.type = cpu_to_le32(GSP_RPC_MIGRATE); msg.subcmd = cpu_to_le32(GSP_MIGRATE_SUBCMD_SAVE); mig_req->src_gpu_id = cpu_to_le64(0x1); mig_req->dst_gpu_id = cpu_to_le64(0x2); mig_req->memory_bitmap = cpu_to_le64(0xFFFFFFFFFFFFFFFF); mig_req->page_table_ptr = cpu_to_le64(0x80000000); mig_req->state = cpu_to_le32(GSP_MIGRATE_SUBCMD_SAVE); mig_req->flags = cpu_to_le32(0); mig_req->context = cpu_to_le64(0); mig_req->reserved = 0; TEST_ASSERT_EQ(le32_to_cpu(msg.type), GSP_RPC_MIGRATE, "MIGRATE RPC type"); TEST_ASSERT_EQ(le32_to_cpu(msg.subcmd), GSP_MIGRATE_SUBCMD_SAVE, "MIGRATE subcmd"); TEST_ASSERT_EQ(le64_to_cpu(mig_req->src_gpu_id), 0x1, "MIGRATE src_gpu_id"); TEST_ASSERT_EQ(le64_to_cpu(mig_req->dst_gpu_id), 0x2, "MIGRATE dst_gpu_id"); TEST_ASSERT_EQ(le64_to_cpu(mig_req->memory_bitmap), 0xFFFFFFFFFFFFFFFF, "MIGRATE memory_bitmap"); TEST_ASSERT_EQ(le64_to_cpu(mig_req->page_table_ptr), 0x80000000, "MIGRATE page_table_ptr"); /* Test RESTORE subcmd */ msg.subcmd = cpu_to_le32(GSP_MIGRATE_SUBCMD_RESTORE); mig_req->state = cpu_to_le32(GSP_MIGRATE_SUBCMD_RESTORE); mig_req->flags = cpu_to_le32(GSP_MIGRATE_SUBCMD_RESTORE); mig_req->context = cpu_to_le64(0xDEADBEEF); TEST_ASSERT_EQ(le32_to_cpu(msg.subcmd), GSP_MIGRATE_SUBCMD_RESTORE, "MIGRATE restore subcmd"); TEST_ASSERT_EQ(le64_to_cpu(mig_req->context), 0xDEADBEEF, "MIGRATE checkpoint context"); return TEST_PASS; } /* ============================================================ * Firmware Address Validation Tests * ============================================================ */ static int test_firmware_addresses(void) { pr_info("=== Testing Firmware Address Constants ===\n"); TEST_ASSERT_EQ(GSP_FW_BASE, 0x04000000UL, "GSP_FW_BASE"); TEST_ASSERT_EQ(GSP_RPC_DISPATCH_PRIMARY, 0x057a1ac0UL, "Primary Dispatcher"); TEST_ASSERT_EQ(GSP_RPC_JUMP_TABLE, 0x057a3ad8UL, "Jump Table"); TEST_ASSERT_EQ(GSP_RPC_DISPATCH_SECONDARY, 0x04ed39dcUL, "Secondary Dispatcher"); TEST_ASSERT_EQ(GSP_RPC_DISPATCH_TERTIARY, 0x04cc58f8UL, "Tertiary Dispatcher"); TEST_ASSERT_EQ(GSP_RPC_DISPATCH_QUATERNARY, 0x05723ef4UL, "Quaternary Dispatcher"); TEST_ASSERT_EQ(GSP_ALLOC_MAIN, 0x057e94ecUL, "ALLOC Main"); TEST_ASSERT_EQ(GSP_SCHEDULE_MAIN, 0x051efbf4UL, "SCHEDULE Main"); TEST_ASSERT_EQ(GSP_BAR_TRAP_HANDLER_JT, 0x057675b7UL, "BAR_TRAP Handler (JT)"); TEST_ASSERT_EQ(GSP_BAR_TRAP_HANDLER_PRIM, 0x04cb8189UL, "BAR_TRAP Handler (Primary)"); TEST_ASSERT_EQ(GSP_PIN_HANDLER_SEC, 0x04ed34b8UL, "PIN Handler (Secondary)"); TEST_ASSERT_EQ(GSP_MAP_HANDLER_A, 0x05766ab7UL, "MAP Handler A"); TEST_ASSERT_EQ(GSP_MAP_HANDLER_B, 0x05778a37UL, "MAP Handler B"); TEST_ASSERT_EQ(GSP_UNMAP_HANDLER_A, 0x057669b7UL, "UNMAP Handler A"); TEST_ASSERT_EQ(GSP_UNMAP_HANDLER_B, 0x05779937UL, "UNMAP Handler B"); TEST_ASSERT_EQ(GSP_PIN_HANDLER_A, 0x057664b7UL, "PIN Handler A"); TEST_ASSERT_EQ(GSP_PIN_HANDLER_B, 0x0577a3b7UL, "PIN Handler B"); TEST_ASSERT_EQ(GSP_UNPIN_HANDLER_A, 0x057682b7UL, "UNPIN Handler A"); TEST_ASSERT_EQ(GSP_UNPIN_HANDLER_B, 0x05779fb7UL, "UNPIN Handler B"); TEST_ASSERT_EQ(GSP_SCHEDULE_HANDLER_A, 0x05767f37UL, "SCHEDULE Handler A"); TEST_ASSERT_EQ(GSP_SCHEDULE_HANDLER_B, 0x0575aeb7UL, "SCHEDULE Handler B"); TEST_ASSERT_EQ(GSP_YIELD_HANDLER_A, 0x0575ae37UL, "YIELD Handler A"); TEST_ASSERT_EQ(GSP_YIELD_HANDLER_B, 0x05767337UL, "YIELD Handler B"); TEST_ASSERT_EQ(GSP_NOTIFY_HANDLER_A, 0x0577c8b7UL, "NOTIFY Handler A"); TEST_ASSERT_EQ(GSP_NOTIFY_HANDLER_B, 0x05767837UL, "NOTIFY Handler B"); TEST_ASSERT_EQ(GSP_ENTRY_POINT, 0x04009000UL, "Entry Point"); return TEST_PASS; } /* ============================================================ * RPC Type/Subcommand Validation Tests * ============================================================ */ static int test_rpc_types(void) { pr_info("=== Testing RPC Type Constants ===\n"); TEST_ASSERT_EQ(GSP_RPC_ALLOC, 0x01, "RPC_ALLOC"); TEST_ASSERT_EQ(GSP_RPC_FREE, 0x02, "RPC_FREE"); TEST_ASSERT_EQ(GSP_RPC_MAP, 0x03, "RPC_MAP"); TEST_ASSERT_EQ(GSP_RPC_UNMAP, 0x04, "RPC_UNMAP"); TEST_ASSERT_EQ(GSP_RPC_PIN, 0x05, "RPC_PIN"); TEST_ASSERT_EQ(GSP_RPC_UNPIN, 0x06, "RPC_UNPIN"); TEST_ASSERT_EQ(GSP_RPC_SCHEDULE, 0x07, "RPC_SCHEDULE"); TEST_ASSERT_EQ(GSP_RPC_YIELD, 0x08, "RPC_YIELD"); TEST_ASSERT_EQ(GSP_RPC_NOTIFY, 0x09, "RPC_NOTIFY"); TEST_ASSERT_EQ(GSP_RPC_BAR_TRAP, 0x0A, "RPC_BAR_TRAP"); TEST_ASSERT_EQ(GSP_RPC_MIGRATE, 0x0B, "RPC_MIGRATE"); TEST_ASSERT_EQ(GSP_RPC_DEBUG, 0xFF, "RPC_DEBUG"); return TEST_PASS; } static int test_alloc_subcmds(void) { pr_info("=== Testing ALLOC Sub-commands ===\n"); TEST_ASSERT_EQ(GSP_ALLOC_SUBCMD_DEFAULT, 0, "ALLOC_SUBCMD_DEFAULT"); TEST_ASSERT_EQ(GSP_ALLOC_SUBCMD_TYPE1, 1, "ALLOC_SUBCMD_TYPE1"); TEST_ASSERT_EQ(GSP_ALLOC_SUBCMD_TYPE2, 3, "ALLOC_SUBCMD_TYPE2"); TEST_ASSERT_EQ(GSP_ALLOC_SUBCMD_TYPE3, 4, "ALLOC_SUBCMD_TYPE3"); TEST_ASSERT_EQ(GSP_ALLOC_SUBCMD_TYPE4, 5, "ALLOC_SUBCMD_TYPE4"); TEST_ASSERT_EQ(GSP_ALLOC_SUBCMD_TYPE5, 8, "ALLOC_SUBCMD_TYPE5"); TEST_ASSERT_EQ(GSP_ALLOC_SUBCMD_TYPE6, 10, "ALLOC_SUBCMD_TYPE6"); TEST_ASSERT_EQ(GSP_ALLOC_SUBCMD_TYPE7, 12, "ALLOC_SUBCMD_TYPE7"); TEST_ASSERT_EQ(GSP_ALLOC_SUBCMD_TYPE8, 17, "ALLOC_SUBCMD_TYPE8"); TEST_ASSERT_EQ(GSP_ALLOC_SUBCMD_TYPE9, 19, "ALLOC_SUBCMD_TYPE9"); TEST_ASSERT_EQ(GSP_ALLOC_SUBCMD_TYPE10, 20, "ALLOC_SUBCMD_TYPE10"); TEST_ASSERT_EQ(GSP_ALLOC_SUBCMD_TYPE11, 21, "ALLOC_SUBCMD_TYPE11"); TEST_ASSERT_EQ(GSP_ALLOC_SUBCMD_TYPE12, 22, "ALLOC_SUBCMD_TYPE12"); TEST_ASSERT_EQ(GSP_ALLOC_SUBCMD_TYPE13, 23, "ALLOC_SUBCMD_TYPE13"); TEST_ASSERT_EQ(GSP_ALLOC_SUBCMD_TYPE14, 24, "ALLOC_SUBCMD_TYPE14"); TEST_ASSERT_EQ(GSP_ALLOC_SUBCMD_TYPE15, 25, "ALLOC_SUBCMD_TYPE15"); TEST_ASSERT_EQ(GSP_ALLOC_SUBCMD_TYPE16, 26, "ALLOC_SUBCMD_TYPE16"); TEST_ASSERT_EQ(GSP_ALLOC_SUBCMD_TYPE17, 27, "ALLOC_SUBCMD_TYPE17"); TEST_ASSERT_EQ(GSP_ALLOC_SUBCMD_TYPE18, 28, "ALLOC_SUBCMD_TYPE18"); TEST_ASSERT_EQ(GSP_ALLOC_SUBCMD_TYPE19, 29, "ALLOC_SUBCMD_TYPE19"); TEST_ASSERT_EQ(GSP_ALLOC_SUBCMD_TYPE20, 30, "ALLOC_SUBCMD_TYPE20"); TEST_ASSERT_EQ(GSP_ALLOC_SUBCMD_TYPE21, 31, "ALLOC_SUBCMD_TYPE21"); return TEST_PASS; } /* ============================================================ * Payload Size Validation * ============================================================ */ static int test_payload_capacity(void) { pr_info("=== Testing Payload Capacity ===\n"); /* gsp_rpc_msg has 6 x u64 payload = 48 bytes */ TEST_ASSERT(sizeof(struct gsp_alloc_req) <= 48, "ALLOC req fits in payload"); TEST_ASSERT(sizeof(struct gsp_map_req) <= 48, "MAP req fits in payload"); TEST_ASSERT(sizeof(struct gsp_pin_req) <= 48, "PIN req fits in payload"); TEST_ASSERT(sizeof(struct gsp_sched_req) <= 48, "SCHED req fits in payload"); TEST_ASSERT(sizeof(struct gsp_bar_trap_req) <= 48, "BAR_TRAP req fits in payload"); /* MIGRATE req is 56 bytes - uses extended payload format */ TEST_ASSERT(sizeof(struct gsp_migrate_req) == 56, "MIGRATE req size is 56 bytes"); return TEST_PASS; } /* ============================================================ * Module Init/Exit * ============================================================ */ static int __init gsp_rpc_test_init(void) { pr_info("========================================\n"); pr_info("GSP RPC Client Test Suite Starting\n"); pr_info("========================================\n"); test_structure_sizes(); test_structure_alignment(); test_rpc_msg_encoding(); test_map_msg_encoding(); test_pin_msg_encoding(); test_sched_msg_encoding(); test_bar_trap_msg_encoding(); test_migrate_msg_encoding(); test_firmware_addresses(); test_rpc_types(); test_alloc_subcmds(); test_payload_capacity(); pr_info("========================================\n"); pr_info("Test Results: %d total, %d passed, %d failed\n", test_count, pass_count, fail_count); pr_info("========================================\n"); if (fail_count > 0) { pr_err("TEST SUITE FAILED\n"); return -EINVAL; } pr_info("TEST SUITE PASSED\n"); return 0; } static void __exit gsp_rpc_test_exit(void) { pr_info("GSP RPC Client Test Suite Exited\n"); } module_init(gsp_rpc_test_init); module_exit(gsp_rpc_test_exit); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Open-IOV Project"); MODULE_DESCRIPTION("GSP RPC Client Test/Validation Harness"); MODULE_VERSION("1.0");