All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv2 0/2] Enable pre-allocated buffer support for driver_data
@ 2017-05-20  6:48 yi1.li
  2017-05-20  6:48 ` [PATCHv2 1/2] firmware: Enable pre-allocated buffer support in driver_data yi1.li
  2017-05-20  6:48 ` [PATCHv2 2/2] test: add pre-allocated buffer to driver_data tester yi1.li
  0 siblings, 2 replies; 3+ messages in thread
From: yi1.li @ 2017-05-20  6:48 UTC (permalink / raw)
  To: mcgrof, atull, gregkh, wagi, dwmw2, rafal, arend.vanspriel, rjw,
	moritz.fischer, pmladek, johannes.berg, emmanuel.grumbach,
	luciano.coelho, kvalo, luto, takahiro.akashi, dhowells, pjones
  Cc: linux-kernel, linux-fpga, Yi Li

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

This series enables the equivalent pre-allocated buffer feature in 
request_firmware_into_buf to driver_data API, so caller can allocate
firmware data buffer and pass to driver_data. This will be used for
streaming support of driver_data, which allow caller to manage the size
and buffer of firmware streaming. 

Changes in v2:

  - Rebase to Luis R. Rodriguez's 20170501-driver-data-try2
    branch 
  - Move alloc_buf and alloc_buf_size to public driver_data_req_params
    structure.
  - Add self test cases.

Yi Li (2):
  firmware: Enable pre-allocated buffer support in driver_data
  test: add pre-allocated buffer to driver_data tester

 drivers/base/firmware_class.c                   | 21 +++-----
 include/linux/driver_data.h                     |  5 ++
 lib/test_driver_data.c                          | 68 ++++++++++++++++++++++++-
 tools/testing/selftests/firmware/driver_data.sh | 36 +++++++++++++
 4 files changed, 116 insertions(+), 14 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCHv2 1/2] firmware: Enable pre-allocated buffer support in driver_data
  2017-05-20  6:48 [PATCHv2 0/2] Enable pre-allocated buffer support for driver_data yi1.li
@ 2017-05-20  6:48 ` yi1.li
  2017-05-20  6:48 ` [PATCHv2 2/2] test: add pre-allocated buffer to driver_data tester yi1.li
  1 sibling, 0 replies; 3+ messages in thread
From: yi1.li @ 2017-05-20  6:48 UTC (permalink / raw)
  To: mcgrof, atull, gregkh, wagi, dwmw2, rafal, arend.vanspriel, rjw,
	moritz.fischer, pmladek, johannes.berg, emmanuel.grumbach,
	luciano.coelho, kvalo, luto, takahiro.akashi, dhowells, pjones
  Cc: linux-kernel, linux-fpga, Yi Li

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

This enables the equivalent feature of the legacy request_firmware_into_buf
to driver_data, so caller can allocate and manage the firmware buffer
instead of by driver_data class internally. The caller need to setup
alloc_buf and alloc_buf_size in the @driver_data_req_params structure.

Signed-off-by: Yi Li <yi1.li@linux.intel.com>
---
 drivers/base/firmware_class.c | 21 ++++++++-------------
 include/linux/driver_data.h   |  5 +++++
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 444c9a8..461c7c2 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -83,9 +83,6 @@ enum driver_data_priv_reqs {
  * @mode: mode of operation
  * @priv_reqs: private set of &enum driver_data_reqs, private requirements for
  * 	the driver data request
- * @alloc_buf: buffer area allocated by the caller so we can place the
- * 	respective driver data
- * @alloc_buf_size: size of the @alloc_buf
  * @old_async_cb: used only for request_firmware_nowait() since we won't change
  * 	all async callbacks to get the return value on failure
  * @api: used internally for keeping track of the currently evaluated API
@@ -98,8 +95,6 @@ enum driver_data_priv_reqs {
 struct driver_data_priv_params {
 	enum driver_data_mode mode;
 	u64 priv_reqs;
-	void *alloc_buf;
-	size_t alloc_buf_size;
 	void (*old_async_cb)(const struct firmware *driver_data, void *context);
 	u8 api;
 	bool retry_api;
@@ -149,12 +144,12 @@ struct driver_data_params {
 #define __DATA_REQ_FIRMWARE_BUF(buf, size)				\
 	.req_params = {							\
 		.reqs = DRIVER_DATA_REQ_NO_CACHE,			\
+		.alloc_buf = &buf,					\
+		.alloc_buf_size = size,					\
 	},								\
 	.priv_params = {						\
 		.priv_reqs = DRIVER_DATA_PRIV_REQ_FALLBACK |		\
 			     DRIVER_DATA_PRIV_REQ_FALLBACK_UEVENT,	\
-		.alloc_buf = buf,					\
-		.alloc_buf_size = size,					\
 	}
 
 #define __DATA_REQ_FIRMWARE_NOWAIT(module, uevent, gfp, async_cb, async_ctx) \
@@ -265,9 +260,9 @@ static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 	void *buf;
 	size_t size;
 
-	if (data_params) {
-		buf = data_params->priv_params.alloc_buf;
-		size = data_params->priv_params.alloc_buf_size;
+	if (data_params && data_params->req_params.alloc_buf) {
+		buf = *data_params->req_params.alloc_buf;
+		size = data_params->req_params.alloc_buf_size;
 	} else {
 		buf = NULL;
 		size = 0;
@@ -507,9 +502,9 @@ static struct firmware_buf *__allocate_fw_buf(const char *fw_name,
 	void *dbuf;
 	size_t size;
 
-	if (data_params) {
-		dbuf = data_params->priv_params.alloc_buf;
-		size = data_params->priv_params.alloc_buf_size;
+	if (data_params && data_params->req_params.alloc_buf) {
+		dbuf = *data_params->req_params.alloc_buf;
+		size = data_params->req_params.alloc_buf_size;
 	} else {
 		dbuf = NULL;
 		size = 0;
diff --git a/include/linux/driver_data.h b/include/linux/driver_data.h
index b6ef5ee..a3a5fbe 100644
--- a/include/linux/driver_data.h
+++ b/include/linux/driver_data.h
@@ -144,6 +144,9 @@ enum driver_data_reqs {
  * 	highest version of API supported by the caller.
  * @api_name_postfix: optional, indicates to use this as the driver data name
  * 	postfix when %DRIVER_DATA_REQ_USE_API_VERSIONING is enabled.
+ * @alloc_buf: pointer of pointer to the buffer area allocated by the caller
+ *	so we can place the respective driver data
+ * @alloc_buf_size: size of the @alloc_buf
  *
  * This data structure is intended to carry all requirements and specifications
  * required to complete the task to get the requested driver date file to the
@@ -157,6 +160,8 @@ struct driver_data_req_params {
 	u8 api_max;
 	const char *api_name_postfix;
 	const union driver_data_cbs cbs;
+	void **alloc_buf;
+	size_t alloc_buf_size;
 };
 
 /*
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCHv2 2/2] test: add pre-allocated buffer to driver_data tester
  2017-05-20  6:48 [PATCHv2 0/2] Enable pre-allocated buffer support for driver_data yi1.li
  2017-05-20  6:48 ` [PATCHv2 1/2] firmware: Enable pre-allocated buffer support in driver_data yi1.li
@ 2017-05-20  6:48 ` yi1.li
  1 sibling, 0 replies; 3+ messages in thread
From: yi1.li @ 2017-05-20  6:48 UTC (permalink / raw)
  To: mcgrof, atull, gregkh, wagi, dwmw2, rafal, arend.vanspriel, rjw,
	moritz.fischer, pmladek, johannes.berg, emmanuel.grumbach,
	luciano.coelho, kvalo, luto, takahiro.akashi, dhowells, pjones
  Cc: linux-kernel, linux-fpga, Yi Li

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

This adds pre-allocated buffer test cases to the simple sync and
async test.

Signed-off-by: Yi Li <yi1.li@linux.intel.com>
---
 lib/test_driver_data.c                          | 68 ++++++++++++++++++++++++-
 tools/testing/selftests/firmware/driver_data.sh | 36 +++++++++++++
 2 files changed, 103 insertions(+), 1 deletion(-)

diff --git a/lib/test_driver_data.c b/lib/test_driver_data.c
index fa7f52b..13fb091 100644
--- a/lib/test_driver_data.c
+++ b/lib/test_driver_data.c
@@ -35,6 +35,7 @@
 #include <linux/async.h>
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
+#include <linux/sizes.h>
 
 /* Used for the fallback default to test against */
 #define TEST_DRIVER_DATA "test-driver_data.bin"
@@ -68,6 +69,9 @@ int num_test_devs;
  *      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.
+ * @prealloc: if set, driver_data will use preallocated buffer for
+ *      firmware_buf->data. The caller need to setup alloc_buf_size and
+ *      alloc_buf in the driver_data_req_params structure.
  * @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
@@ -117,6 +121,7 @@ struct test_config {
 	bool optional;
 	bool keep;
 	bool no_cache;
+	bool prealloc;
 	bool enable_opt_cb;
 	bool use_api_versioning;
 	u8 api_min;
@@ -345,6 +350,9 @@ static ssize_t config_show(struct device *dev,
 	len += snprintf(buf+len, PAGE_SIZE,
 			"no_cache:\t\t%s\n",
 			config->no_cache ? "true" : "false");
+	len += snprintf(buf+len, PAGE_SIZE,
+			"prealloc:\t\t%s\n",
+			config->prealloc ? "true" : "false");
 
 	mutex_unlock(&test_dev->config_mutex);
 
@@ -450,10 +458,13 @@ static int trigger_config_sync(struct driver_data_test_device *test_dev)
 {
 	struct test_config *config = &test_dev->config;
 	int ret;
+	void *buf;
 	const struct driver_data_req_params req_params_default = {
 		DRIVER_DATA_DEFAULT_SYNC_REQS(config_sync_req_cb, test_dev,
 					      DRIVER_DATA_REQ_OPTIONAL |
-					      DRIVER_DATA_REQ_KEEP)
+					      DRIVER_DATA_REQ_KEEP),
+		.alloc_buf_size = (config->prealloc ? SZ_4K : 0),
+		.alloc_buf = (config->prealloc ? &buf : NULL),
 	};
 	const struct driver_data_req_params req_params_opt_cb = {
 		DRIVER_DATA_DEFAULT_SYNC(config_sync_req_cb, test_dev),
@@ -462,6 +473,8 @@ static int trigger_config_sync(struct driver_data_test_device *test_dev)
 		.reqs = (config->optional ? DRIVER_DATA_REQ_OPTIONAL : 0) |
 			(config->keep ? DRIVER_DATA_REQ_KEEP : 0) |
 			(config->no_cache ? DRIVER_DATA_REQ_NO_CACHE : 0),
+		.alloc_buf_size = (config->prealloc ? SZ_4K : 0),
+		.alloc_buf = (config->prealloc ? &buf : NULL),
 	};
 	const struct driver_data_req_params *req_params;
 
@@ -470,11 +483,22 @@ static int trigger_config_sync(struct driver_data_test_device *test_dev)
 	else
 		req_params = &req_params_default;
 
+	if (config->prealloc) {
+		buf = kmalloc(SZ_4K, GFP_KERNEL);
+		if (!buf) {
+			dev_err(test_dev->dev, "%s: kmalloc buf failed\n",
+				__func__);
+			return -ENOMEM;
+		}
+	}
 	ret = driver_data_request_sync(config->name, req_params, test_dev->dev);
 	if (ret)
 		dev_err(test_dev->dev, "sync load of '%s' failed: %d\n",
 			config->name, ret);
 
+	if (config->prealloc)
+		kfree(buf);
+
 	return ret;
 }
 
@@ -524,11 +548,14 @@ static int trigger_config_async(struct driver_data_test_device *test_dev)
 {
 	struct test_config *config = &test_dev->config;
 	int ret;
+	void *buf;
 	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->no_cache ? DRIVER_DATA_REQ_NO_CACHE : 0),
+		.alloc_buf_size = (config->prealloc ? SZ_4K : 0),
+		.alloc_buf = (config->prealloc ? &buf : NULL),
 	};
 	const struct driver_data_req_params req_params_opt_cb = {
 		DRIVER_DATA_DEFAULT_ASYNC(config_async_req_cb, test_dev),
@@ -536,6 +563,8 @@ static int trigger_config_async(struct driver_data_test_device *test_dev)
 		.reqs = (config->optional ? DRIVER_DATA_REQ_OPTIONAL : 0) |
 			(config->keep ? DRIVER_DATA_REQ_KEEP : 0) |
 			(config->no_cache ? DRIVER_DATA_REQ_NO_CACHE : 0),
+		.alloc_buf_size = (config->prealloc ? SZ_4K : 0),
+		.alloc_buf = (config->prealloc ? &buf : NULL),
 	};
 	const struct driver_data_req_params req_params_api = {
 		DRIVER_DATA_API_CB(config_async_req_api_cb, test_dev),
@@ -544,6 +573,8 @@ static int trigger_config_async(struct driver_data_test_device *test_dev)
 			(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),
+		.alloc_buf_size = (config->prealloc ? SZ_4K : 0),
+		.alloc_buf = (config->prealloc ? &buf : NULL),
 	};
 	const struct driver_data_req_params *req_params;
 
@@ -554,6 +585,14 @@ static int trigger_config_async(struct driver_data_test_device *test_dev)
 	else
 		req_params = &req_params_default;
 
+	if (config->prealloc) {
+		buf = kmalloc(SZ_4K, GFP_KERNEL);
+		if (!buf) {
+			dev_err(test_dev->dev, "%s: kmalloc buf failed\n",
+				__func__);
+			return -ENOMEM;
+		}
+	}
 	test_dev->api_found_calls = 0;
 	ret = driver_data_request_async(config->name, req_params,
 					test_dev->dev);
@@ -574,6 +613,8 @@ static int trigger_config_async(struct driver_data_test_device *test_dev)
 	wait_for_completion_timeout(&test_dev->request_complete, 5 * HZ);
 
 out:
+	if (config->prealloc)
+		kfree(buf);
 	return ret;
 }
 
@@ -669,6 +710,7 @@ static int __driver_data_config_init(struct test_config *config)
 	config->optional = false;
 	config->keep = false;
 	config->no_cache = false;
+	config->prealloc = false;
 	config->enable_opt_cb = false;
 	config->use_api_versioning = false;
 	config->api_min = 0;
@@ -1011,6 +1053,29 @@ static ssize_t config_no_cache_show(struct device *dev,
 static DEVICE_ATTR(config_no_cache, 0644, config_no_cache_show,
 		   config_no_cache_store);
 
+static ssize_t config_prealloc_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->prealloc);
+}
+
+static ssize_t config_prealloc_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->prealloc);
+}
+static DEVICE_ATTR(config_prealloc, 0644, config_prealloc_show,
+		   config_prealloc_store);
+
 static ssize_t config_enable_opt_cb_store(struct device *dev,
 					  struct device_attribute *attr,
 					  const char *buf, size_t count)
@@ -1169,6 +1234,7 @@ static struct attribute *test_dev_attrs[] = {
 	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_prealloc),
 	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),
diff --git a/tools/testing/selftests/firmware/driver_data.sh b/tools/testing/selftests/firmware/driver_data.sh
index 82fae0a..dcbbc78 100755
--- a/tools/testing/selftests/firmware/driver_data.sh
+++ b/tools/testing/selftests/firmware/driver_data.sh
@@ -228,6 +228,22 @@ config_disable_no_cache()
 	fi
 }
 
+config_set_prealloc()
+{
+	if ! echo -n 1 >$DIR/config_prealloc; then
+		echo "$0: Unable to set to prealloc" >&2
+		exit 1
+	fi
+}
+
+config_disable_prealloc()
+{
+	if ! echo -n 0 >$DIR/config_prealloc; then
+		echo "$0: Unable to disable prealloc option" >&2
+		exit 1
+	fi
+}
+
 config_enable_opt_cb()
 {
 	if ! echo -n 1 >$DIR/config_enable_opt_cb; then
@@ -559,12 +575,32 @@ driver_data_test_0004a_no_cache()
 	config_expect_result ${FUNCNAME[0]} SUCCESS
 }
 
+driver_data_test_0004s_prealloc()
+{
+	driver_data_set_sync_defaults
+	config_set_prealloc
+	config_trigger ${FUNCNAME[0]}
+	config_file_should_match ${FUNCNAME[0]}
+	config_expect_result ${FUNCNAME[0]} SUCCESS
+}
+
+driver_data_test_0004a_prealloc()
+{
+	driver_data_set_async_defaults
+	config_set_prealloc
+	config_trigger ${FUNCNAME[0]}
+	config_file_should_match ${FUNCNAME[0]}
+	config_expect_result ${FUNCNAME[0]} SUCCESS
+}
+
 driver_data_test_0004()
 {
 	driver_data_test_0004s
 	driver_data_test_0004a
 	driver_data_test_0004s_no_cache
 	driver_data_test_0004a_no_cache
+	driver_data_test_0004s_prealloc
+	driver_data_test_0004a_prealloc
 }
 
 driver_data_test_0005s()
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2017-05-20  6:53 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-20  6:48 [PATCHv2 0/2] Enable pre-allocated buffer support for driver_data yi1.li
2017-05-20  6:48 ` [PATCHv2 1/2] firmware: Enable pre-allocated buffer support in driver_data yi1.li
2017-05-20  6:48 ` [PATCHv2 2/2] test: add pre-allocated buffer to driver_data tester yi1.li

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.