M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions
@@ -0,0 +1,31 @@
ifeq ($(call is-vendor-board-platform,QCOM),true)
ifeq ($(TARGET_ARCH),arm)
DLKM_DIR := device/qcom/common/dlkm
LOCAL_PATH := $(call my-dir)
# the dlkm
include $(CLEAR_VARS)
LOCAL_MODULE := msm_ocmem_test_module.ko
LOCAL_MODULE_TAGS := debug
include $(DLKM_DIR)/AndroidKernelModule.mk
# the userspace test program
include $(CLEAR_VARS)
LOCAL_MODULE := ocmem_test
LOCAL_SRC_FILES := ocmem_test.c
LOCAL_MODULE_TAGS := debug
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/kernel-tests
include $(BUILD_EXECUTABLE)
# the test script
include $(CLEAR_VARS)
LOCAL_MODULE := ocmem_test.sh
LOCAL_SRC_FILES := ocmem_test.sh
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_MODULE_TAGS := debug
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/kernel-tests
include $(BUILD_PREBUILT)
endif
endif
@@ -0,0 +1 @@
obj-m := msm_ocmem_test_module.o
@@ -0,0 +1,27 @@
ocmemdir = $(prefix)/ocmem
ocmem_PROGRAMS = ocmem_test
ocmem_test_LDADD = -lpthread -lrt
ocmem_SCRIPTS = ocmem_test.sh run.sh
KERNEL_FLAGS ?= ARCH=arm
EXTRA_CFLAGS = -DDEBUG
module = msm_ocmem_test_module.ko
kmake = $(MAKE) $(KERNEL_FLAGS) -C $(KERNEL_DIR) M=$(CURDIR)
$(module):
$(kmake) modules
all-local: $(module)
install-exec-local: $(module)
$(kmake) INSTALL_MOD_PATH=$(DESTDIR)$(prefix)/modules modules_install
# "make distclean" will always run clean-local in this directory,
# regardless of the KERNELMODULES conditional. Therefore, ensure
# KERNEL_DIR exists before running clean. Further, don't fail even
# if there is a problem.
clean-local:
-test ! -d "$(KERNEL_DIR)" || $(kmake) clean
@@ -0,0 +1,35 @@
Test: ocmem_test
Usage steps:
# On android:
adb shell
cd /data/kernel-tests
sh ocmem_test.sh [OPTIONS]
# On kdev
/kernel-test/ocmem/run.sh [OPTIONS]
OPTIONS can be:
-n OR --nominal Nominal test (Run by default)
-a OR --adversarial Adversarial tests
-r OR --repeatability [Number of iterations] Repeatability tests
-v OR --verbose Run with debug messages enabled
Description:
Nominal Test:
1. Invoke all OCMEM APIs used by performance mode clients.
2. Invoke all OCMEM APIs used by low power clients.
Adversarial Tests:
1. Invoke all invalid combinations of OCMEM APIs.
Repeatability Tests:
1. Run nominal and adversarial test cases for number of iterations
specified or a maximum of 10 iterations.
Stress tests:
To be defined.
Targets supported: 8974
@@ -0,0 +1,511 @@
/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/delay.h>
#include <linux/memory.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <mach/irqs.h>
#include <mach/ocmem.h>
#define OCMEM_KERNEL_TEST_MAGIC 0xc1
#define OCMEM_TEST_TYPE_NOMINAL \
_IO(OCMEM_KERNEL_TEST_MAGIC, 1)
#define OCMEM_TEST_TYPE_ADVERSARIAL \
_IO(OCMEM_KERNEL_TEST_MAGIC, 2)
#define OCMEM_TEST_TYPE_STRESS \
_IO(OCMEM_KERNEL_TEST_MAGIC, 3)
#define OCMEM_TEST_VERBOSE_MODE \
_IO(OCMEM_KERNEL_TEST_MAGIC, 4)
#define OCMEM_TEST_DEBUG_MODE \
_IO(OCMEM_KERNEL_TEST_MAGIC, 5)
#define TEST_OCMEM_CLIENT OCMEM_GRAPHICS
/* "OCMM" */
#define OCMEM_READ_WRITE_MAGIC 0xA110CA7E
#define OCMEM_MAX_SIZE 0x180000
#define OCMEM_BASE_ADDR 0xFEC00000
static int debug_mode;
static int verbose_mode;
static int num_test_cases;
static int num_success;
static unsigned long test_ocmem_client_quota;
#define OCMEM_LOG(msg, args...) do { \
if (verbose_mode) \
pr_info(msg, ##args); \
else \
pr_debug(msg, ##args); \
} while (0)
static inline int ocmem_phys_address(unsigned long addr)
{
if (addr <= OCMEM_MAX_SIZE)
addr += OCMEM_BASE_ADDR;
return addr;
}
static int test_client_notif_handler(struct notifier_block *this,
unsigned long event, void *data)
{
struct ocmem_buf *buff = data;
OCMEM_LOG("ocmem_test: test_client notitification event %lu\n", event);
OCMEM_LOG("Notification buffer buff %p(addr %lx:len %lx)\n",
buff, buff->addr, buff->len);
return NOTIFY_DONE;
}
static struct notifier_block test_client_nb = {
.notifier_call = test_client_notif_handler,
};
#ifdef CONFIG_MSM_OCMEM_NONSECURE
static int ocmem_verify_access(int id, struct ocmem_buf *buffer)
{
unsigned long start;
unsigned long sz = buffer->len;
unsigned i = 0;
unsigned failures = 0;
void *vstart = NULL;
unsigned *ptr = NULL;
start = ocmem_phys_address(buffer->addr);
OCMEM_LOG("io-remapping addr %lx and len %lx\n", start, sz);
vstart = ioremap_nocache(start, sz);
if (!vstart) {
pr_err("ocmem test: ioremap failed\n");
return -ENOMEM;
}
ptr = (unsigned *)vstart;
for (i = 0; i < sz/(sizeof(int)); i++) {
ptr[i] = OCMEM_READ_WRITE_MAGIC;
/* Ensure that the value was written out to OCMEM memory */
mb();
if (ptr[i] != OCMEM_READ_WRITE_MAGIC) {
pr_err("ocmem test: verify access failed for client %d\n",
id);
failures++;
}
}
OCMEM_LOG("read write test for memory range %lx to %lx completed\n",
start, start + sz - 1);
iounmap(vstart);
return failures;
}
#else
static int ocmem_verify_access(int id, struct ocmem_buf *buffer)
{
OCMEM_LOG("Secure mode, skipping read/write verification\n");
return 0;
}
#endif
/*
* Test Case: Single Allocation Test
* Invokes: Synchronous allocation call
* Verifies: A buffer of "size" is allocated when there is no contention
*/
static int ocmem_test_single_alloc(void)
{
struct ocmem_buf *buff = NULL;
unsigned long size = test_ocmem_client_quota;
num_test_cases++;
buff = ocmem_allocate(TEST_OCMEM_CLIENT, test_ocmem_client_quota);
if (!buff || !buff->len)
return -EINVAL;
OCMEM_LOG("ocmem test: single_alloc: buff %p(addr:%lx len:%lx)\n",
buff, buff->addr, buff->len);
if (buff->len != size)
return -EINVAL;
ocmem_verify_access(TEST_OCMEM_CLIENT, buff);
if (ocmem_free(TEST_OCMEM_CLIENT, buff))
return -EINVAL;
OCMEM_LOG("ocmem test: single_alloc succeeded\n");
return 0;
}
/*
* Test Case: Single Allocation No Wait Test
* Invokes: Synchronous no wait allocation call
* Verifies: A buffer of "size" is allocated when there is no contention
*/
static int ocmem_test_single_alloc_nowait(void)
{
struct ocmem_buf *buff = NULL;
unsigned long size = test_ocmem_client_quota;
num_test_cases++;
buff = ocmem_allocate_nowait(TEST_OCMEM_CLIENT, size);
if (!buff || !buff->len)
return -EINVAL;
OCMEM_LOG("ocmem test: single_alloc_nw: buff %p(addr:%lx len:%lx)\n",
buff, buff->addr, buff->len);
if (buff->len != size)
return -EINVAL;
ocmem_verify_access(TEST_OCMEM_CLIENT, buff);
if (ocmem_free(TEST_OCMEM_CLIENT, buff))
return -EINVAL;
OCMEM_LOG("ocmem test: single_alloc_nw succeeded\n");
num_success++;
return 0;
}
/*
* Test Case: Single Allocation Range Test
* Invokes: Range allocation call
* Verifies: A buffer of size "max" is allocated when there is no contention
*/
static int ocmem_test_single_alloc_range(void)
{
struct ocmem_buf *buff = NULL;
void *test_client_hndl = NULL;
unsigned long min = test_ocmem_client_quota / 2;
unsigned long max = test_ocmem_client_quota;
unsigned long step = min;
num_test_cases++;
test_client_hndl = ocmem_notifier_register(TEST_OCMEM_CLIENT, &test_client_nb);
if (!test_client_hndl)
goto notifier_fail;
buff = ocmem_allocate_range(TEST_OCMEM_CLIENT, min, max, step);
if (!buff || !buff->len)
goto test_case_fail;
OCMEM_LOG("ocmem test: single_alloc_range: buff %p(addr:%lx len:%lx)\n",
buff, buff->addr, buff->len);
if (buff->len != max)
goto test_case_fail;
if (ocmem_free(TEST_OCMEM_CLIENT, buff))
goto test_case_fail;
if (ocmem_notifier_unregister(test_client_hndl, &test_client_nb))
return -EINVAL;
num_success++;
OCMEM_LOG("ocmem test: single_alloc_range succeeded\n");
return 0;
test_case_fail:
if (ocmem_notifier_unregister(test_client_hndl, &test_client_nb))
return -EINVAL;
notifier_fail:
return -EINVAL;
}
/*
* Test Case: Single Allocation Non blocking Test
* Invokes: Non blocking allocation call
* Verifies: A buffer of "size" is immediately allocated during no contention
*/
static int ocmem_test_single_alloc_nb(void)
{
struct ocmem_buf *buff = NULL;
void *test_client_hndl;
unsigned long size = test_ocmem_client_quota;
num_test_cases++;
test_client_hndl = ocmem_notifier_register(TEST_OCMEM_CLIENT, &test_client_nb);
if (!test_client_hndl)
goto notifier_fail;
buff = ocmem_allocate_nb(TEST_OCMEM_CLIENT, size);
if (!buff || !buff->len)
goto test_case_fail;
OCMEM_LOG("ocmem test: single_alloc_nb: buff %p(addr: %lx len:%lx)\n",
buff, buff->addr, buff->len);
if (buff->len != size)
goto test_case_fail;
if (ocmem_free(TEST_OCMEM_CLIENT, buff))
goto test_case_fail;
if (ocmem_notifier_unregister(test_client_hndl, &test_client_nb))
return -EINVAL;
num_success++;
OCMEM_LOG("ocmem test: single_alloc_nb succeeded\n");
return 0;
test_case_fail:
if (ocmem_notifier_unregister(test_client_hndl, &test_client_nb))
return -EINVAL;
notifier_fail:
return -EINVAL;
}
static int (*nominal_test_cases[]) (void) = {
ocmem_test_single_alloc,
ocmem_test_single_alloc_nowait,
ocmem_test_single_alloc_nb,
ocmem_test_single_alloc_range,
};
static int msm_ocmem_nominal_test(void)
{
unsigned errors = 0;
int rc = 0;
unsigned i = 0;
OCMEM_LOG("OCMEM test: Nominal test suite invoked\n");
for (i = 0; i < ARRAY_SIZE(nominal_test_cases); i++) {
OCMEM_LOG("Nominal test case %d\n", i);
rc = nominal_test_cases[i]();
if (rc < 0) {
pr_err("ocmem test: nominal: test case %d failed\n", i);
errors++;
/* Bail out on first failure if debug mode is not set */
if (!debug_mode)
return -EINVAL;
}
}
OCMEM_LOG("OCMEM test: Nominal test completed with %d errors\n",
errors);
return errors;
}
/*
* Test Case: Allocation Denied Test
* Invokes: Synchronous allocation call
* Verifies: A subystem that is not allowed OCMEM memory must be denied alloc
*/
static int ocmem_test_alloc_denied(void)
{
struct ocmem_buf *buff = NULL;
unsigned long size = test_ocmem_client_quota;
num_test_cases++;
buff = ocmem_allocate(OCMEM_VOICE, size);
if (buff != NULL)
return -EINVAL;
OCMEM_LOG("ocmem test: alloc_denied: NULL buffer returned\n");
num_success++;
return 0;
}
static int (*adversarial_test_cases[]) (void) = {
ocmem_test_alloc_denied,
};
static int msm_ocmem_adversarial_test(void)
{
unsigned errors = 0;
unsigned i = 0;
int rc = 0;
OCMEM_LOG("OCMEM test: Adversarial test suite invoked\n");
for (i = 0; i < ARRAY_SIZE(adversarial_test_cases); i++) {
OCMEM_LOG("Adversarial test case %d\n", i);
rc = adversarial_test_cases[i]();
if (rc < 0) {
pr_err("ocmem test: adversarial: test case %d failed\n",
i);
errors++;
/* Bail out on first failure if debug mode is not set */
if (!debug_mode)
return -EINVAL;
}
}
OCMEM_LOG("OCMEM test: Adversarial test completed with %d errors\n",
errors);
return errors;
}
static int msm_ocmem_stress_test(void)
{
OCMEM_LOG("OCMEM test: Stress test suite invoked\n");
return 0;
}
static long msm_ocmem_test_ioctl(struct file *file, unsigned cmd,
unsigned long arg)
{
long retval = 0;
int err = 0;
OCMEM_LOG("OCMEM test: ioctl invoked");
/* Verify user space ioctl arguments */
if (_IOC_TYPE(cmd) != OCMEM_KERNEL_TEST_MAGIC) {
pr_err("OCMEM test: Unknown IOCTL type, ignoring\n");
return -ENOTTY;
}
if (_IOC_DIR(cmd) & _IOC_READ)
err = !access_ok(VERIFY_WRITE, (void __user *)arg,
_IOC_SIZE(cmd));
else if (_IOC_DIR(cmd) & _IOC_WRITE)
err = !access_ok(VERIFY_READ, (void __user *)arg,
_IOC_SIZE(cmd));
if (err)
return -EFAULT;
switch (cmd) {
case OCMEM_TEST_DEBUG_MODE:
if (__get_user(debug_mode, (int __user *)arg))
return -EINVAL;
if (debug_mode) {
pr_info("OCMEM test: Enabling debug mode\n");
pr_info("Continue testing all testcases in case of failure\n");
}
break;
case OCMEM_TEST_VERBOSE_MODE:
if (__get_user(verbose_mode, (int __user *)arg))
return -EINVAL;
if (verbose_mode)
pr_info("OCMEM test: Verbose logging enabled\n");
break;
case OCMEM_TEST_TYPE_NOMINAL:
retval = msm_ocmem_nominal_test();
break;
case OCMEM_TEST_TYPE_ADVERSARIAL:
retval = msm_ocmem_adversarial_test();
break;
case OCMEM_TEST_TYPE_STRESS:
retval = msm_ocmem_stress_test();
break;
default:
pr_err("OCMEM test: Invalid ioctl\n");
retval = -EFAULT;
break;
}
return retval;
}
/*
* Register ourselves as a misc device to be able to test the OCMEM code
* from userspace.
*/
static const struct file_operations msm_ocmem_test_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = msm_ocmem_test_ioctl,
};
static struct miscdevice msm_ocmem_test_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "ocmemtest",
.fops = &msm_ocmem_test_fops,
};
/*
* Module Init.
*/
static int __init ocmem_test_init(void)
{
int ret;
pr_info("OCMEM test: Init\n");
ret = misc_register(&msm_ocmem_test_dev);
if (ret < 0) {
pr_err("OCMEM test: Failed to register device");
return -ENODEV;
}
test_ocmem_client_quota = get_max_quota(TEST_OCMEM_CLIENT);
if (!test_ocmem_client_quota) {
pr_err("Couldn't do get_max_quota for TEST_OCMEM_CLIENT (id: %d)\n",
TEST_OCMEM_CLIENT);
ret = -EIO;
goto fail;
}
pr_info("OCMEM test: Module loaded\n");
ret = 0;
return ret;
fail:
misc_deregister(&msm_ocmem_test_dev);
return ret;
}
/*
* Module Exit.
*/
static void __exit ocmem_test_exit(void)
{
pr_info("OCMEM test: Exit\n");
misc_deregister(&msm_ocmem_test_dev);
pr_info("OCMEM test: Module unloaded\n");
}
module_init(ocmem_test_init);
module_exit(ocmem_test_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Test for MSM On-Chip Memory");
@@ -0,0 +1,286 @@
/*
* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <getopt.h>
#include <unistd.h>
#define OCMEM_KERNEL_TEST_MAGIC 0xc1
#define OCMEM_TEST_TYPE_NOMINAL \
_IO(OCMEM_KERNEL_TEST_MAGIC, 1)
#define OCMEM_TEST_TYPE_ADVERSARIAL \
_IO(OCMEM_KERNEL_TEST_MAGIC, 2)
#define OCMEM_TEST_TYPE_STRESS \
_IO(OCMEM_KERNEL_TEST_MAGIC, 3)
#define OCMEM_TEST_VERBOSE_MODE \
_IO(OCMEM_KERNEL_TEST_MAGIC, 4)
#define OCMEM_TEST_DEBUG_MODE \
_IO(OCMEM_KERNEL_TEST_MAGIC, 5)
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
#define NUM_ITERATIONS (10)
static int ocmem_dev_fd;
static int iterations;
static int verbosity;
#define pr_debug(msg, args...) do { \
if (verbosity) \
printf("\n"msg, ##args);\
} while (0)
#define pr_err(msg, args...) do { \
fprintf(stderr, "\n"msg, ##args);\
} while (0)
enum test_types {
NOMINAL,
ADVERSARIAL,
STRESS,
REPEAT,
};
struct option testopts[] = {
{"Nominal", no_argument, NULL, 'n'},
{"Adversarial", no_argument, NULL, 'a'},
{"Stress", no_argument, NULL, 's'},
{"Repeatability", required_argument, NULL, 'r'},
{"Verbose", no_argument, NULL, 'v'},
{"Help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0},
};
static void usage(int ret)
{
printf("Usage: ocmem_test [OPTIONS] [TEST_TYPE]...\n"
"Runs the kernel mode ocmem tests specified by the TEST_TYPE\n"
"parameter. If no TEST_TYPE is specified, then the nominal\n"
" test is run.\n"
"\n"
"OPTIONS can be:\n"
" -v, --verbose run with debug messages enabled\n"
"\n"
"TEST_TYPE can be:\n"
" -n, --nominal run standard functionality tests\n"
" -a, --adversarial run tests that try to break the\n"
" driver\n"
" -s, --stress run tests that try to maximize the\n"
" capacity of the driver\n"
" -r, --repeatability run specified iterations of both the\n"
" nominal and adversarial tests\n");
exit(ret);
}
static unsigned int parse_command(int argc, char *const argv[])
{
int command;
unsigned ret = 0;
while ((command = getopt_long(argc, argv, "vnashr:", testopts,
NULL)) != -1) {
switch (command) {
case 'v':
verbosity = 1;
break;
case 'n':
ret |= 1 << NOMINAL;
break;
case 'a':
ret |= 1 << ADVERSARIAL;
break;
case 's':
ret |= 1 << STRESS;
break;
case 'r':
ret |= 1 << REPEAT;
if (optarg) {
iterations = atoi(optarg);
if (iterations <= 0)
iterations = NUM_ITERATIONS;
printf("Iterations: %d\n\n", iterations);
} else {
iterations = NUM_ITERATIONS;
printf("Using default iterations: %d\n",
iterations);
}
break;
case 'h':
usage(0);
default:
usage(-1);
}
}
return ret;
}
static int nominal_test(void)
{
int errors = 0;
int ret = 0;
pr_debug("OCMEM nominal test iocl invoked\n");
ret = ioctl(ocmem_dev_fd, OCMEM_TEST_TYPE_NOMINAL);
if (ret == -ENOTTY || ret == -EFAULT || ret == -EINVAL) {
pr_err("Failed to invoke ioctl (errno:%d)\n", ret);
exit(-1);
}
if (ret < 0) {
pr_err("OCMEM nominal test FAILED; failures %d\n", ret);
errors++;
}
return errors;
}
static int stress_test(void)
{
int errors = 0;
int ret = 0;
pr_debug("OCMEM nominal test ioctl invoked\n");
ret = ioctl(ocmem_dev_fd, OCMEM_TEST_TYPE_STRESS);
if (ret == -ENOTTY || ret == -EFAULT || ret == -EINVAL) {
pr_err("Failed to invoke ioctl (errno:%d)\n", ret);
exit(-1);
}
if (ret < 0) {
pr_err("OCMEM stress test FAILED; failures %d\n", ret);
errors++;
}
return errors;
}
static int adversarial_test(void)
{
int errors = 0;
int ret = 0;
pr_debug("OCMEM adversarial test ioctl invoked\n");
ret = ioctl(ocmem_dev_fd, OCMEM_TEST_TYPE_ADVERSARIAL);
if (ret == -ENOTTY || ret == -EFAULT || ret == -EINVAL) {
pr_err("Failed to invoke ioctl (errno:%d)\n", ret);
exit(-1);
}
if (ret < 0) {
pr_err("OCMEM adversarial test FAILED; failures %d\n", ret);
errors++;
}
return errors;
}
static int repeat_test(void)
{
unsigned int i = 0;
int errors = 0;
pr_debug("OCMEM repeat test invoked for %d iterations\n", iterations);
for (i = 0; i < iterations; i++) {
pr_debug("Repeat test iteration %d\n", i);
errors += nominal_test();
errors += stress_test();
}
return errors;
}
static int (*test_func[]) () = {
[NOMINAL] = nominal_test,
[ADVERSARIAL] = adversarial_test,
[STRESS] = stress_test,
[REPEAT] = repeat_test,
};
int main(int argc, char **argv)
{
int rc = -1;
int num_failures = 0;
unsigned int i = 0;
unsigned int test_mask = parse_command(argc, argv);
ocmem_dev_fd = open("/dev/ocmemtest", O_RDWR | O_SYNC);
if (ocmem_dev_fd < 0) {
pr_err("Failed to open OCMEM device\n");
return rc;
}
pr_debug("OCMEM opened ocmem_dev_fd (%d) successfully\n",
ocmem_dev_fd);
if (verbosity) {
if (ioctl(ocmem_dev_fd, OCMEM_TEST_VERBOSE_MODE,
&verbosity) < 0)
pr_err("Failed to set verbose mode in DLKM\n");
}
for (i = 0; i < (int)ARRAY_SIZE(test_func); i++) {
/* Look for the test that was selected */
if (!(test_mask & (1U << i)))
continue;
/* This test was selected, so run it */
rc = test_func[i]();
if (rc) {
pr_err("%s test case FAILED! rc:%d\n",
testopts[i].name, rc);
num_failures += rc;
}
}
if (num_failures)
pr_err("OCMEM: NUMBER OF TESTS FAILED: %d\n", num_failures);
close(ocmem_dev_fd);
pr_debug("OCMEM test exiting with %d failures\n", num_failures);
return -num_failures;
}
@@ -0,0 +1,120 @@
# Copyright (c) 2012, The Linux Foundation. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of The Linux Foundation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
chmod 755 ocmem_test
if [ -d /system/lib/modules/ ]; then
modpath=/system/lib/modules
else
modpath=/kernel-tests/modules/lib/modules/$(uname -r)/extra
fi
ocmem_test_mod=${modpath}/msm_ocmem_test_module.ko
ocmem_test_dev_misc=/sys/class/misc/ocmemtest/dev
ocmem_test_dev=/dev/ocmemtest
CMD_LINE="$@"
NUM_ARGS=$#
maybe_make_node()
{
thedev=$1
themisc=$2
[ -e $thedev ] || \
mknod $thedev c $(cut -d: -f1 $themisc) $(cut -d: -f2 $themisc)
}
#Parse the args for valid switches
while [ $# -gt 0 ]; do
case $1 in
-n | --nominal)
shift 1
;;
-a | --adversarial)
shift 1
;;
-r | --repeatability)
shift 1
if [ "$1" -eq "$1" ] ; then
echo "Specified $1 iterations"
shift 1
else
echo "Invalid number of iterations"
exit 1
fi
;;
-s | --stress)
shift 1
;;
-v | --verbose)
shift 1
;;
-h | --help | *)
exit 1
;;
esac
done
# insert the msm_ocmem_test_module if needed
if [ ! -e $ocmem_test_dev_misc ]; then
insmod $ocmem_test_mod
if [ $? -ne 0 ]; then
echo "ERROR: failed to load module $ocmem_test_mod"
exit 1
fi
fi
# create the ocmem test device if it doesn't exist
maybe_make_node $ocmem_test_dev $ocmem_test_dev_misc
# Execute the tests
# Run nominal test case by default if there are no args
if [ $NUM_ARGS -ne 0 ]; then
./ocmem_test $CMD_LINE
else
echo "Running nominal tests (default)"
./ocmem_test -n
fi
num_failures=$?
# Check for pass or fail status
if [ $num_failures -ne 0 ]; then
echo "OCMEM tests failed ($num_failures)"
rc=1
else
echo "OCMEM tests passed"
rc=0
fi
echo "Unloading $MSM_OCMEM_TEST_MODULE.ko"
rmmod $ocmem_test_mod
exit $rc
@@ -0,0 +1,31 @@
#! /bin/sh --
# Copyright (c) 2012, The Linux Foundation. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of The Linux Foundation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
set -e
cd `dirname $0` && exec ./ocmem_test.sh $@