Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752348AbdFPXEb (ORCPT ); Fri, 16 Jun 2017 19:04:31 -0400 Received: from mga02.intel.com ([134.134.136.20]:36305 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751836AbdFPXE3 (ORCPT ); Fri, 16 Jun 2017 19:04:29 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.39,348,1493708400"; d="scan'208";a="1161474094" From: yi1.li@linux.intel.com To: mcgrof@kernel.org Cc: gregkh@linuxfoundation.org, atull@kernel.org, wagi@monom.org, dwmw2@infradead.org, rafal@milecki.pl, arend.vanspriel@broadcom.com, rjw@rjwysocki.net, moritz.fischer@ettus.com, pmladek@suse.com, johannes.berg@intel.com, emmanuel.grumbach@intel.com, luciano.coelho@intel.com, kvalo@codeaurora.org, luto@kernel.org, takahiro.akashi@linaro.org, dhowells@redhat.com, pjones@redhat.com, linux-kernel@vger.kernel.org, linux-fpga@vger.kernel.org, Yi Li Subject: [PATCHv3 3/3] test: add no_cache to driver_data load tester Date: Fri, 16 Jun 2017 17:58:31 -0500 Message-Id: <1497653911-11944-4-git-send-email-yi1.li@linux.intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1497653911-11944-1-git-send-email-yi1.li@linux.intel.com> References: <1497653911-11944-1-git-send-email-yi1.li@linux.intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 12454 Lines: 362 From: Yi Li Add a platform device to enable PM cache and add cache/no_cache test. Signed-off-by: Yi Li --- 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 #include #include +#include +#include /* 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