#include <linux/cleanup.h>
#include <linux/pm_runtime.h>
#include <kunit/device.h>
#include <kunit/test.h>
#define DEVICE_NAME "pm_runtime_test_device"
static void pm_runtime_depth_test(struct kunit *test)
{
struct device *dev = kunit_device_register(test, DEVICE_NAME);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
pm_runtime_enable(dev);
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
KUNIT_EXPECT_EQ(test, 0, pm_runtime_get_sync(dev));
KUNIT_EXPECT_TRUE(test, pm_runtime_active(dev));
KUNIT_EXPECT_EQ(test, 1, pm_runtime_get_sync(dev));
KUNIT_EXPECT_EQ(test, 0, pm_runtime_put_sync(dev));
KUNIT_EXPECT_EQ(test, 0, pm_runtime_put_sync(dev));
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
}
static void pm_runtime_already_suspended_test(struct kunit *test)
{
struct device *dev = kunit_device_register(test, DEVICE_NAME);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
pm_runtime_enable(dev);
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
pm_runtime_get_noresume(dev);
KUNIT_EXPECT_EQ(test, 0, pm_runtime_barrier(dev));
pm_runtime_put(dev);
pm_runtime_get_noresume(dev);
KUNIT_EXPECT_EQ(test, 1, pm_runtime_put_sync(dev));
KUNIT_EXPECT_EQ(test, 1, pm_runtime_suspend(dev));
KUNIT_EXPECT_EQ(test, 1, pm_runtime_autosuspend(dev));
KUNIT_EXPECT_EQ(test, 1, pm_request_autosuspend(dev));
pm_runtime_get_noresume(dev);
KUNIT_EXPECT_EQ(test, 1, pm_runtime_put_sync_autosuspend(dev));
pm_runtime_get_noresume(dev);
pm_runtime_put_autosuspend(dev);
pm_runtime_get_noresume(dev);
pm_runtime_get_noresume(dev);
KUNIT_EXPECT_EQ(test, 0, pm_runtime_put_sync_autosuspend(dev));
KUNIT_EXPECT_EQ(test, 1, pm_runtime_put_sync_autosuspend(dev));
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
}
static void pm_runtime_idle_test(struct kunit *test)
{
struct device *dev = kunit_device_register(test, DEVICE_NAME);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
pm_runtime_enable(dev);
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
KUNIT_EXPECT_EQ(test, 0, pm_runtime_get_sync(dev));
KUNIT_EXPECT_TRUE(test, pm_runtime_active(dev));
KUNIT_EXPECT_EQ(test, -EAGAIN, pm_runtime_idle(dev));
KUNIT_EXPECT_TRUE(test, pm_runtime_active(dev));
pm_runtime_put_noidle(dev);
KUNIT_EXPECT_TRUE(test, pm_runtime_active(dev));
KUNIT_EXPECT_EQ(test, 0, pm_runtime_idle(dev));
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
KUNIT_EXPECT_EQ(test, -EAGAIN, pm_runtime_idle(dev));
KUNIT_EXPECT_EQ(test, -EAGAIN, pm_request_idle(dev));
}
static void pm_runtime_disabled_test(struct kunit *test)
{
struct device *dev = kunit_device_register(test, DEVICE_NAME);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
KUNIT_EXPECT_FALSE(test, pm_runtime_enabled(dev));
KUNIT_EXPECT_TRUE(test, pm_runtime_active(dev));
KUNIT_EXPECT_FALSE(test, pm_runtime_suspended(dev));
KUNIT_EXPECT_EQ(test, -EACCES, pm_runtime_get(dev));
pm_runtime_put(dev);
KUNIT_EXPECT_EQ(test, -EACCES, pm_runtime_get_sync(dev));
KUNIT_EXPECT_EQ(test, -EACCES, pm_runtime_put_sync(dev));
KUNIT_EXPECT_EQ(test, -EACCES, pm_runtime_get(dev));
pm_runtime_put_autosuspend(dev);
KUNIT_EXPECT_EQ(test, -EACCES, pm_runtime_resume_and_get(dev));
KUNIT_EXPECT_EQ(test, -EACCES, pm_runtime_idle(dev));
KUNIT_EXPECT_EQ(test, -EACCES, pm_request_idle(dev));
KUNIT_EXPECT_EQ(test, -EACCES, pm_request_resume(dev));
KUNIT_EXPECT_EQ(test, -EACCES, pm_request_autosuspend(dev));
KUNIT_EXPECT_EQ(test, -EACCES, pm_runtime_suspend(dev));
KUNIT_EXPECT_EQ(test, -EACCES, pm_runtime_resume(dev));
KUNIT_EXPECT_EQ(test, -EACCES, pm_runtime_autosuspend(dev));
KUNIT_EXPECT_TRUE(test, pm_runtime_active(dev));
KUNIT_EXPECT_FALSE(test, pm_runtime_enabled(dev));
}
static void pm_runtime_error_test(struct kunit *test)
{
struct device *dev = kunit_device_register(test, DEVICE_NAME);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
pm_runtime_enable(dev);
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
dev->power.runtime_error = -EIO;
KUNIT_EXPECT_EQ(test, -EINVAL, pm_runtime_get(dev));
pm_runtime_put(dev);
KUNIT_EXPECT_EQ(test, -EINVAL, pm_runtime_get_sync(dev));
KUNIT_EXPECT_EQ(test, -EINVAL, pm_runtime_put_sync(dev));
KUNIT_EXPECT_EQ(test, -EINVAL, pm_runtime_get(dev));
pm_runtime_put_autosuspend(dev);
KUNIT_EXPECT_EQ(test, -EINVAL, pm_runtime_get(dev));
KUNIT_EXPECT_EQ(test, -EINVAL, pm_runtime_put_sync_autosuspend(dev));
KUNIT_EXPECT_EQ(test, -EINVAL, pm_runtime_resume_and_get(dev));
KUNIT_EXPECT_EQ(test, -EINVAL, pm_runtime_idle(dev));
KUNIT_EXPECT_EQ(test, -EINVAL, pm_request_idle(dev));
KUNIT_EXPECT_EQ(test, -EINVAL, pm_request_resume(dev));
KUNIT_EXPECT_EQ(test, -EINVAL, pm_request_autosuspend(dev));
KUNIT_EXPECT_EQ(test, -EINVAL, pm_runtime_suspend(dev));
KUNIT_EXPECT_EQ(test, -EINVAL, pm_runtime_resume(dev));
KUNIT_EXPECT_EQ(test, -EINVAL, pm_runtime_autosuspend(dev));
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
KUNIT_EXPECT_EQ(test, -EIO, dev->power.runtime_error);
KUNIT_EXPECT_EQ(test, 0, pm_runtime_set_suspended(dev));
KUNIT_EXPECT_EQ(test, 0, dev->power.runtime_error);
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
KUNIT_EXPECT_EQ(test, 0, pm_runtime_get(dev));
KUNIT_EXPECT_EQ(test, 1, pm_runtime_barrier(dev));
pm_runtime_put(dev);
pm_runtime_suspend(dev);
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
KUNIT_EXPECT_EQ(test, 0, pm_runtime_get_sync(dev));
KUNIT_EXPECT_EQ(test, 0, pm_runtime_put_sync(dev));
KUNIT_EXPECT_EQ(test, 0, pm_runtime_get_sync(dev));
pm_runtime_put_autosuspend(dev);
KUNIT_EXPECT_EQ(test, 0, pm_runtime_resume_and_get(dev));
KUNIT_EXPECT_EQ(test, -EAGAIN, pm_runtime_idle(dev));
KUNIT_EXPECT_EQ(test, -EAGAIN, pm_request_idle(dev));
KUNIT_EXPECT_EQ(test, 1, pm_request_resume(dev));
KUNIT_EXPECT_EQ(test, -EAGAIN, pm_request_autosuspend(dev));
KUNIT_EXPECT_EQ(test, -EAGAIN, pm_runtime_suspend(dev));
KUNIT_EXPECT_EQ(test, 1, pm_runtime_resume(dev));
KUNIT_EXPECT_EQ(test, -EAGAIN, pm_runtime_autosuspend(dev));
KUNIT_EXPECT_EQ(test, 0, pm_runtime_put_sync(dev));
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
}
static void pm_runtime_probe_active_test(struct kunit *test)
{
struct device *dev = kunit_device_register(test, DEVICE_NAME);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
KUNIT_EXPECT_TRUE(test, pm_runtime_status_suspended(dev));
KUNIT_EXPECT_EQ(test, 0, pm_runtime_set_active(dev));
KUNIT_EXPECT_TRUE(test, pm_runtime_active(dev));
pm_runtime_enable(dev);
KUNIT_EXPECT_TRUE(test, pm_runtime_active(dev));
KUNIT_EXPECT_EQ(test, 0, pm_runtime_barrier(dev));
KUNIT_EXPECT_TRUE(test, pm_runtime_active(dev));
KUNIT_EXPECT_EQ(test, 0, pm_runtime_idle(dev));
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
}
static struct kunit_case pm_runtime_test_cases[] = {
KUNIT_CASE(pm_runtime_depth_test),
KUNIT_CASE(pm_runtime_already_suspended_test),
KUNIT_CASE(pm_runtime_idle_test),
KUNIT_CASE(pm_runtime_disabled_test),
KUNIT_CASE(pm_runtime_error_test),
KUNIT_CASE(pm_runtime_probe_active_test),
{}
};
static struct kunit_suite pm_runtime_test_suite = {
.name = "pm_runtime_test_cases",
.test_cases = pm_runtime_test_cases,
};
kunit_test_suite(pm_runtime_test_suite);
MODULE_DESCRIPTION("Runtime power management unit test suite");
MODULE_LICENSE("GPL");