Index: firmware_class.c
===================================================================
RCS file: /sources/repository/external_source/linux/linux-2.6.12.2/drivers/base/firmware_class.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -p -u -r1.1 -r1.2
--- firmware_class.c	17 Jan 2006 16:49:35 -0000	1.1
+++ firmware_class.c	15 Feb 2006 14:01:29 -0000	1.2
@@ -31,6 +31,7 @@ enum {
 };
 
 static int loading_timeout = 10;	/* In seconds */
+static char grow_faster = 1;      /* Boolean */
 
 /* fw_lock could be moved to 'struct firmware_priv' but since it is just
  * guarding for corner cases a global lock should be OK */
@@ -79,6 +80,28 @@ firmware_timeout_store(struct class *cla
 
 static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store);
 
+static ssize_t
+firmware_grow_faster_show(struct class *class, char *buf)
+{
+	return sprintf(buf, "%d\n", grow_faster);
+}
+
+/**
+ * firmware_grow_faster_store:
+ * Description:
+ *	Sets or clears a flag that causes the reallocate routine to
+ *	grow the firmware buffer size more or less quickly.
+ *  
+ **/
+static ssize_t
+firmware_grow_faster_store(struct class *class, const char *buf, size_t count)
+{
+	grow_faster = simple_strtol(buf, NULL, 10) != 0;
+	return count;
+}
+
+static CLASS_ATTR(grow_faster, 0644, firmware_grow_faster_show, firmware_grow_faster_store);
+
 static void  fw_class_dev_release(struct class_device *class_dev);
 int firmware_class_hotplug(struct class_device *dev, char **envp,
 			   int num_envp, char *buffer, int buffer_size);
@@ -198,18 +221,27 @@ static int
 fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
 {
 	u8 *new_data;
+  int new_size;
 
 	if (min_size <= fw_priv->alloc_size)
 		return 0;
 
-	new_data = vmalloc(fw_priv->alloc_size + PAGE_SIZE);
+#define ONE_MEG (1024 * 1024)
+
+  new_size = grow_faster 
+    ? ((fw_priv->alloc_size >= ONE_MEG)
+      ? (fw_priv->alloc_size + ONE_MEG)
+      : ((fw_priv->alloc_size >= PAGE_SIZE) ? (fw_priv->alloc_size * 2) : PAGE_SIZE))
+    : (fw_priv->alloc_size + PAGE_SIZE);
+  new_data = vmalloc (new_size);
 	if (!new_data) {
-		printk(KERN_ERR "%s: unable to alloc buffer\n", __FUNCTION__);
+		printk(KERN_ERR "%s: unable to alloc buffer old size %d new size %d\n",
+      __FUNCTION__, fw_priv->alloc_size, new_size);
 		/* Make sure that we don't keep incomplete data */
 		fw_load_abort(fw_priv);
 		return -ENOMEM;
 	}
-	fw_priv->alloc_size += PAGE_SIZE;
+  fw_priv->alloc_size = new_size;
 	if (fw_priv->fw->data) {
 		memcpy(new_data, fw_priv->fw->data, fw_priv->fw->size);
 		vfree(fw_priv->fw->data);
@@ -249,6 +281,13 @@ firmware_data_write(struct kobject *kobj
 		goto out;
 
 	memcpy(fw->data + offset, buffer, count);
+  /*  A successful write should cause us to reset the timeout
+  delay, as very large firmware files might take a while to
+  send through the sysfs file.  We have the fw_lock taken at
+  the moment but the timeout function doesn't lock as it only
+  has to set a single volatile bit, so we're ok to mod it. */
+  if (timer_pending (&fw_priv->timeout))
+    mod_timer (&fw_priv->timeout, jiffies + loading_timeout * HZ);
 
 	fw->size = max_t(size_t, offset + count, fw->size);
 	retval = count;
@@ -568,6 +607,12 @@ firmware_class_init(void)
 		       __FUNCTION__);
 		class_unregister(&firmware_class);
 	}
+	error = class_create_file(&firmware_class, &class_attr_grow_faster);
+	if (error) {
+		printk(KERN_ERR "%s: class_create_file failed\n",
+		       __FUNCTION__);
+		class_unregister(&firmware_class);
+	}
 	return error;
 
 }
