From: Yi Li <yi1...@linux.intel.com>

Add a platform device to enable PM cache and add cache/no_cache test.

Signed-off-by: Yi Li <yi1...@linux.intel.com>
---
 lib/test_driver_data.c                          | 97 ++++++++++++++++++++++---
 tools/testing/selftests/firmware/driver_data.sh | 67 +++++++++++++++++
 2 files changed, 154 insertions(+), 10 deletions(-)

diff --git a/lib/test_driver_data.c b/lib/test_driver_data.c
index c176527..cadd122 100644
--- a/lib/test_driver_data.c
+++ b/lib/test_driver_data.c
@@ -44,6 +44,8 @@
 #include <linux/async.h>
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
 
 /* Used for the fallback default to test against */
 #define TEST_DRIVER_DATA "test-driver_data.bin"
@@ -73,6 +75,10 @@ int num_test_devs;
  *     struct driver_data_reg_params @optional field for more information.
  * @keep: whether or not we wish to free the driver_data on our own, refer to
  *     the struct driver_data_req_params @keep field for more information.
+ * @no_cache: whether or not we wish to use the internal caching mechanism
+ *      to assist drivers from fetching driver data at resume time after
+ *      suspend, refer to the struct driver_data_req_params .req
+ *      DRIVER_DATA_REQ_NO_CACHE for more information.
  * @enable_opt_cb: whether or not the optional callback should be set
  *     on a trigger. There is no equivalent setting on the struct
  *     driver_data_req_params as this is implementation specific, and in
@@ -121,6 +127,7 @@ struct test_config {
        bool async;
        bool optional;
        bool keep;
+       bool no_cache;
        bool enable_opt_cb;
        bool use_api_versioning;
        u8 api_min;
@@ -163,6 +170,7 @@ struct test_driver_data_private {
  *     a driver might typically use to stuff firmware / driver_data.
  * @misc_dev: we use a misc device under the hood
  * @dev: pointer to misc_dev's own struct device
+ * @pdev: pointer to platform device's struct device
  * @api_found_calls: number of calls a fetch for a driver was found. We use
  *     for internal use on the api callback.
  * @driver_data_mutex: for access into the @driver_data, the fake storage
@@ -181,6 +189,7 @@ struct driver_data_test_device {
        struct test_driver_data_private test_driver_data;
        struct miscdevice misc_dev;
        struct device *dev;
+       struct device *pdev;
 
        u8 api_found_calls;
 
@@ -346,6 +355,9 @@ static ssize_t config_show(struct device *dev,
        len += snprintf(buf+len, PAGE_SIZE,
                        "keep:\t\t%s\n",
                        config->keep ? "true" : "false");
+       len += snprintf(buf + len, PAGE_SIZE,
+                       "no_cache:\t\t%s\n",
+                       config->no_cache ? "true" : "false");
 
        mutex_unlock(&test_dev->config_mutex);
 
@@ -399,9 +411,9 @@ static int config_req_default(struct 
driver_data_test_device *test_dev)
                         config->default_name);
 
        ret = driver_data_request_sync(config->default_name,
-                                      &req_params, test_dev->dev);
+                                      &req_params, test_dev->pdev);
        if (ret)
-               dev_info(test_dev->dev,
+               dev_info(test_dev->pdev,
                         "load of default '%s' failed: %d\n",
                         config->default_name, ret);
 
@@ -456,14 +468,17 @@ static int trigger_config_sync(struct 
driver_data_test_device *test_dev)
                                              (config->optional ?
                                               DRIVER_DATA_REQ_OPTIONAL : 0) |
                                              (config->keep ?
-                                              DRIVER_DATA_REQ_KEEP : 0)),
+                                              DRIVER_DATA_REQ_KEEP : 0) |
+                                             (config->no_cache ?
+                                              DRIVER_DATA_REQ_NO_CACHE : 0)),
        };
        const struct driver_data_req_params req_params_opt_cb = {
                DRIVER_DATA_DEFAULT_SYNC(config_sync_req_cb, test_dev),
                DRIVER_DATA_SYNC_OPT_CB(config_sync_req_default_cb,
                                             test_dev),
                .reqs = (config->optional ? DRIVER_DATA_REQ_OPTIONAL : 0) |
-                       (config->keep ? DRIVER_DATA_REQ_KEEP : 0),
+                       (config->keep ? DRIVER_DATA_REQ_KEEP : 0) |
+                       (config->no_cache ? DRIVER_DATA_REQ_NO_CACHE : 0),
        };
        const struct driver_data_req_params *req_params;
 
@@ -472,9 +487,10 @@ static int trigger_config_sync(struct 
driver_data_test_device *test_dev)
        else
                req_params = &req_params_default;
 
-       ret = driver_data_request_sync(config->name, req_params, test_dev->dev);
+       ret = driver_data_request_sync(config->name, req_params,
+                                      test_dev->pdev);
        if (ret)
-               dev_err(test_dev->dev, "sync load of '%s' failed: %d\n",
+               dev_err(test_dev->pdev, "sync load of '%s' failed: %d\n",
                        config->name, ret);
 
        return ret;
@@ -529,19 +545,22 @@ static int trigger_config_async(struct 
driver_data_test_device *test_dev)
        const struct driver_data_req_params req_params_default = {
                DRIVER_DATA_DEFAULT_ASYNC(config_async_req_cb, test_dev),
                .reqs = (config->optional ? DRIVER_DATA_REQ_OPTIONAL : 0) |
-                       (config->keep ? DRIVER_DATA_REQ_KEEP : 0),
+                       (config->keep ? DRIVER_DATA_REQ_KEEP : 0) |
+                       (config->no_cache ? DRIVER_DATA_REQ_NO_CACHE : 0),
        };
        const struct driver_data_req_params req_params_opt_cb = {
                DRIVER_DATA_DEFAULT_ASYNC(config_async_req_cb, test_dev),
                DRIVER_DATA_ASYNC_OPT_CB(config_async_req_default_cb, test_dev),
                .reqs = (config->optional ? DRIVER_DATA_REQ_OPTIONAL : 0) |
-                       (config->keep ? DRIVER_DATA_REQ_KEEP : 0),
+                       (config->keep ? DRIVER_DATA_REQ_KEEP : 0) |
+                       (config->no_cache ? DRIVER_DATA_REQ_NO_CACHE : 0),
        };
        const struct driver_data_req_params req_params_api = {
                DRIVER_DATA_API_CB(config_async_req_api_cb, test_dev),
                DRIVER_DATA_API(config->api_min, config->api_max, 
config->api_name_postfix),
                .reqs = (config->optional ? DRIVER_DATA_REQ_OPTIONAL : 0) |
                        (config->keep ? DRIVER_DATA_REQ_KEEP : 0) |
+                       (config->no_cache ? DRIVER_DATA_REQ_NO_CACHE : 0) |
                        (config->use_api_versioning ? 
DRIVER_DATA_REQ_USE_API_VERSIONING : 0),
        };
        const struct driver_data_req_params *req_params;
@@ -555,9 +574,9 @@ static int trigger_config_async(struct 
driver_data_test_device *test_dev)
 
        test_dev->api_found_calls = 0;
        ret = driver_data_request_async(config->name, req_params,
-                                       test_dev->dev);
+                                       test_dev->pdev);
        if (ret) {
-               dev_err(test_dev->dev, "async load of '%s' failed: %d\n",
+               dev_err(test_dev->pdev, "async load of '%s' failed: %d\n",
                        config->name, ret);
                goto out;
        }
@@ -667,6 +686,7 @@ static int __driver_data_config_init(struct test_config 
*config)
        config->async = false;
        config->optional = false;
        config->keep = false;
+       config->no_cache = false;
        config->enable_opt_cb = false;
        config->use_api_versioning = false;
        config->api_min = 0;
@@ -986,6 +1006,29 @@ static ssize_t config_keep_show(struct device *dev,
 }
 static DEVICE_ATTR(config_keep, 0644, config_keep_show, config_keep_store);
 
+static ssize_t config_no_cache_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       struct driver_data_test_device *test_dev = dev_to_test_dev(dev);
+       struct test_config *config = &test_dev->config;
+
+       return test_dev_config_update_bool(test_dev, buf, count,
+                                          &config->no_cache);
+}
+
+static ssize_t config_no_cache_show(struct device *dev,
+                                   struct device_attribute *attr,
+                                   char *buf)
+{
+       struct driver_data_test_device *test_dev = dev_to_test_dev(dev);
+       struct test_config *config = &test_dev->config;
+
+       return test_dev_config_show_bool(test_dev, buf, config->no_cache);
+}
+static DEVICE_ATTR(config_no_cache, 0644, config_no_cache_show,
+                  config_no_cache_store);
+
 static ssize_t config_enable_opt_cb_store(struct device *dev,
                                          struct device_attribute *attr,
                                          const char *buf, size_t count)
@@ -1143,6 +1186,7 @@ static struct attribute *test_dev_attrs[] = {
        TEST_DRIVER_DATA_DEV_ATTR(config_async),
        TEST_DRIVER_DATA_DEV_ATTR(config_optional),
        TEST_DRIVER_DATA_DEV_ATTR(config_keep),
+       TEST_DRIVER_DATA_DEV_ATTR(config_no_cache),
        TEST_DRIVER_DATA_DEV_ATTR(config_use_api_versioning),
        TEST_DRIVER_DATA_DEV_ATTR(config_enable_opt_cb),
        TEST_DRIVER_DATA_DEV_ATTR(config_api_min),
@@ -1163,10 +1207,32 @@ void free_test_dev_driver_data(struct 
driver_data_test_device *test_dev)
        vfree(test_dev);
 }
 
+static struct platform_device *driver_data_pdev;
+static int driver_data_test_suspend(struct device *dev)
+{
+       return 0;
+}
+
+static int driver_data_test_resume(struct device *dev)
+{
+       return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(driver_test_platform_pm_ops, driver_data_test_suspend,
+       driver_data_test_resume);
+
+static struct platform_driver driver_data_test_driver = {
+       .driver = {
+               .name   = "driver_data_test",
+               .pm = &driver_test_platform_pm_ops,
+       }
+};
+
 void unregister_test_dev_driver_data(struct driver_data_test_device *test_dev)
 {
        wait_for_completion_timeout(&test_dev->request_complete, 5 * HZ);
        dev_info(test_dev->dev, "removing interface\n");
+       platform_device_unregister(driver_data_pdev);
        misc_deregister(&test_dev->misc_dev);
        free_test_dev_driver_data(test_dev);
 }
@@ -1211,6 +1277,11 @@ struct driver_data_test_device 
*alloc_test_dev_driver_data(int idx)
        return NULL;
 }
 
+static int driver_data_probe(struct platform_device *pdev)
+{
+       return 0;
+}
+
 static int register_test_dev_driver_data(void)
 {
        struct driver_data_test_device *test_dev = NULL;
@@ -1230,6 +1301,12 @@ static int register_test_dev_driver_data(void)
                goto out;
        }
 
+       driver_data_pdev = platform_create_bundle(
+               &driver_data_test_driver, driver_data_probe, NULL, 0, NULL, 0);
+       if (IS_ERR(driver_data_pdev))
+               return PTR_ERR(driver_data_pdev);
+       test_dev->pdev = &driver_data_pdev->dev;
+
        ret = misc_register(&test_dev->misc_dev);
        if (ret) {
                pr_err("could not register misc device: %d\n", ret);
diff --git a/tools/testing/selftests/firmware/driver_data.sh 
b/tools/testing/selftests/firmware/driver_data.sh
index dc823ae..15af500 100755
--- a/tools/testing/selftests/firmware/driver_data.sh
+++ b/tools/testing/selftests/firmware/driver_data.sh
@@ -48,6 +48,8 @@ ALL_TESTS="$ALL_TESTS 0010:10:1"
 ALL_TESTS="$ALL_TESTS 0011:10:1"
 ALL_TESTS="$ALL_TESTS 0012:1:1"
 ALL_TESTS="$ALL_TESTS 0013:1:1"
+ALL_TESTS="$ALL_TESTS 0015:1:1"
+ALL_TESTS="$ALL_TESTS 0016:1:1"
 
 # Not yet sure how to automate suspend test well yet.  For now we expect a
 # manual run. If using qemu you can resume a guest using something like the
@@ -219,6 +221,22 @@ config_disable_keep()
        fi
 }
 
+config_set_no_cache()
+{
+       if ! echo -n 1 >$DIR/config_no_cache; then
+               echo "$0: Unable to set to no_cache" >&2
+               exit 1
+       fi
+}
+
+config_disable_no_cache()
+{
+       if ! echo -n 0 >$DIR/config_no_cache; then
+               echo "$0: Unable to disable no_cache option" >&2
+               exit 1
+       fi
+}
+
 config_enable_opt_cb()
 {
        if ! echo -n 1 >$DIR/config_enable_opt_cb; then
@@ -412,6 +430,30 @@ config_default_file_should_not_match()
        echo "$1: OK!"
 }
 
+config_expect_cached()
+{
+       echo -n 1 > /sys/kernel/debug/firmware/cache
+       if ! cat /sys/kernel/debug/firmware/cache | grep "cached 
test-driver_data.bin"; then
+               echo "$1: FAIL to cache firmware" >&2
+               echo -n 0 > /sys/kernel/debug/firmware/cache
+               exit 1
+       fi
+       echo "$1: OK! cache success"
+       echo -n 0 > /sys/kernel/debug/firmware/cache
+}
+
+config_expect_non_cached()
+{
+       echo -n 1 > /sys/kernel/debug/firmware/cache
+       if cat /sys/kernel/debug/firmware/cache | grep "cached 
driver_data_test_no_cache.bin"; then
+               echo "$1: FAIL, should not cache firmware" >&2
+               echo -n 0 > /sys/kernel/debug/firmware/cache
+               exit 1
+       fi
+       echo "$1: OK! expect non cache success"
+       echo -n 0 > /sys/kernel/debug/firmware/cache
+}
+
 config_expect_result()
 {
        RC=$(config_get_test_result)
@@ -821,6 +863,29 @@ driver_data_test_0014()
        driver_data_test_0014a
 }
 
+driver_data_test_0015()
+{
+       driver_data_set_sync_defaults
+       config_disable_no_cache
+       config_trigger ${FUNCNAME[0]}
+       config_expect_cached ${FUNCNAME[0]}
+}
+
+driver_data_test_0016()
+{
+       NAME_PREFIX="driver_data_test_no_cache"
+       NAME_POSTFIX=".bin"
+       NAME="${NAME_PREFIX}${NAME_POSTFIX}"
+
+       config_add_api_file $NAME
+
+       driver_data_set_sync_defaults
+       config_set_name $NAME
+       config_set_no_cache
+       config_trigger ${FUNCNAME[0]}
+       config_expect_non_cached ${FUNCNAME[0]}
+       config_rm_api_file $NAME
+}
 list_tests()
 {
        echo "Test ID list:"
@@ -843,6 +908,8 @@ list_tests()
        echo "0012 x $(get_test_count 0012) - Verify api call wills will hunt 
for files, ignore file"
        echo "0013 x $(get_test_count 0013) - Verify api call works"
        echo "0014 x $(get_test_count 0013) - Verify api call works with 
suspend + resume"
+       echo "0015 x $(get_test_count 0016) - Verify cache works"
+       echo "0016 x $(get_test_count 0017) - Verify non-cache works"
 }
 
 test_reqs
-- 
2.7.4

Reply via email to