Web lists-archives.com

[PATCHv3 3/3] test: add no_cache to driver_data load tester




From: Yi Li <yi1.li@xxxxxxxxxxxxxxx>

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

Signed-off-by: Yi Li <yi1.li@xxxxxxxxxxxxxxx>
---
 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