public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Clemens Ladisch <clemens@ladisch.de>
To: Ira Snyder <iws@ovro.caltech.edu>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>,
	Andrey Borzenkov <arvidjaar@mail.ru>,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH] firmware: speed up request_firmware()
Date: Fri, 03 Apr 2009 08:46:11 +0200	[thread overview]
Message-ID: <49D5B0B3.2040405@ladisch.de> (raw)
In-Reply-To: <20090128203421.GC31107@ovro.caltech.edu>

Ira Snyder wrote:
> I didn't want to change an existing kernel interface, so I just made
> the easiest change that worked for me.

Well, userspace does know the actual size of the image, so I see no
reason why it shouldn't be able to tell the kernel about it beforehand.

> I'd be happy to test patches anyone comes up with.

=====

This adds a data_size attribute to the firmware loading device so that
userspace can tell us about the firmware image size.  This allows us to
preallocate the buffer with the final size, thus avoiding reallocating
the buffer for every page of data as it comes in.

Signed-off-by: Clemens Ladisch <clemens@ladisch.de>

--- linux-2.6.orig/Documentation/firmware_class/README
+++ linux-2.6/Documentation/firmware_class/README
@@ -21,7 +21,7 @@
  kernel(driver): calls request_firmware(&fw_entry, $FIRMWARE, device)
 
  userspace:
- 	- /sys/class/firmware/xxx/{loading,data} appear.
+ 	- /sys/class/firmware/xxx/{loading,data,data_size} appear.
 	- hotplug gets called with a firmware identifier in $FIRMWARE
 	  and the usual hotplug environment.
 		- hotplug: echo 1 > /sys/class/firmware/xxx/loading
@@ -29,11 +29,13 @@
  kernel: Discard any previous partial load.
 
  userspace:
+		- hotplug: echo ... > /sys/class/firmware/xxx/data_size
 		- hotplug: cat appropriate_firmware_image > \
 					/sys/class/firmware/xxx/data
 
- kernel: grows a buffer in PAGE_SIZE increments to hold the image as it
-	 comes in.
+ kernel: Copies the firmware image into a buffer of the specified size.
+	 If the image is larger, the buffer automatically grows in
+	 PAGE_SIZE increments.
 
  userspace:
 		- hotplug: echo 0 > /sys/class/firmware/xxx/loading
@@ -60,6 +62,9 @@
 
 	HOTPLUG_FW_DIR=/usr/lib/hotplug/firmware/
 
+	if [ -e /sys/$DEVPATH/data_size ]; then
+		stat -c %s $HOTPLUG_FW_DIR/$FIRMWARE > /sys/$DEVPATH/data_size
+	fi
 	echo 1 > /sys/$DEVPATH/loading
 	cat $HOTPLUG_FW_DIR/$FIRMWARE > /sysfs/$DEVPATH/data
 	echo 0 > /sys/$DEVPATH/loading
@@ -73,6 +78,9 @@
  - firmware_data_read() and firmware_loading_show() are just provided
    for testing and completeness, they are not called in normal use.
 
+ - /sys/class/firmware/xxx/data_size is optional for compatibility with
+   older kernels.
+
  - There is also /sys/class/firmware/timeout which holds a timeout in
    seconds for the whole load operation.
 
--- linux-2.6.orig/Documentation/firmware_class/hotplug-script
+++ linux-2.6/Documentation/firmware_class/hotplug-script
@@ -6,6 +6,9 @@
 
 HOTPLUG_FW_DIR=/usr/lib/hotplug/firmware/
 
+if [ -e /sys/$DEVPATH/data_size ]; then
+	stat -c %s $HOTPLUG_FW_DIR/$FIRMWARE > /sys/$DEVPATH/data_size
+fi
 echo 1 > /sys/$DEVPATH/loading
 cat $HOTPLUG_FW_DIR/$FIRMWARE > /sys/$DEVPATH/data
 echo 0 > /sys/$DEVPATH/loading
--- linux-2.6.orig/drivers/base/firmware_class.c
+++ linux-2.6/drivers/base/firmware_class.c
@@ -46,6 +46,7 @@ struct firmware_priv {
 	struct firmware *fw;
 	unsigned long status;
 	int alloc_size;
+	int size_hint;
 	struct timer_list timeout;
 };
 
@@ -114,6 +115,32 @@ static struct class firmware_class = {
 	.dev_release	= fw_dev_release,
 };
 
+static ssize_t firmware_data_size_show(struct device *dev,
+				       struct device_attribute *attr, char *buf)
+{
+	struct firmware_priv *fw_priv = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", fw_priv->size_hint);
+}
+
+static ssize_t firmware_data_size_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	struct firmware_priv *fw_priv = dev_get_drvdata(dev);
+	long value;
+	int err;
+
+	err = strict_strtol(buf, 10, &value);
+	if (err)
+		return err;
+	fw_priv->size_hint = value;
+	return count;
+}
+
+static DEVICE_ATTR(data_size, 0644,
+		   firmware_data_size_show, firmware_data_size_store);
+
 static ssize_t firmware_loading_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
@@ -207,6 +234,7 @@ fw_realloc_buffer(struct firmware_priv *
 	if (min_size <= fw_priv->alloc_size)
 		return 0;
 
+	min_size = max(min_size, fw_priv->size_hint);
 	new_size = ALIGN(min_size, PAGE_SIZE);
 	new_data = vmalloc(new_size);
 	if (!new_data) {
@@ -359,6 +387,12 @@ static int fw_setup_device(struct firmwa
 		goto error_unreg;
 	}
 
+	retval = device_create_file(f_dev, &dev_attr_data_size);
+	if (retval) {
+		dev_err(device, "%s: device_create_file failed\n", __func__);
+		goto error_unreg;
+	}
+
 	retval = device_create_file(f_dev, &dev_attr_loading);
 	if (retval) {
 		dev_err(device, "%s: device_create_file failed\n", __func__);

  reply	other threads:[~2009-04-03  6:46 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-01-28 18:04 [PATCH] firmware: speed up request_firmware() Ira Snyder
2009-01-28 18:11 ` Alan Cox
2009-01-28 18:35   ` Matt Mackall
2009-01-28 19:03 ` Andrey Borzenkov
2009-01-28 19:45   ` Alan Cox
2009-01-28 20:34     ` Ira Snyder
2009-04-03  6:46       ` Clemens Ladisch [this message]
2009-04-03 17:25         ` Andrey Borzenkov
2009-04-06  8:43           ` Clemens Ladisch
2009-04-09 19:08       ` David Woodhouse
2009-04-10  5:03         ` David Woodhouse

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=49D5B0B3.2040405@ladisch.de \
    --to=clemens@ladisch.de \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=arvidjaar@mail.ru \
    --cc=iws@ovro.caltech.edu \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox