Merge branch 'master'
[powerpc.git] / drivers / base / firmware_class.c
index 6522814..98f6c02 100644 (file)
@@ -28,6 +28,7 @@ enum {
        FW_STATUS_DONE,
        FW_STATUS_ABORT,
        FW_STATUS_READY,
+       FW_STATUS_READY_NOHOTPLUG,
 };
 
 static int loading_timeout = 10;       /* In seconds */
@@ -61,14 +62,16 @@ firmware_timeout_show(struct class *class, char *buf)
 }
 
 /**
- * firmware_timeout_store:
- * Description:
+ * firmware_timeout_store - set number of seconds to wait for firmware
+ * @class: device class pointer
+ * @buf: buffer to scan for timeout value
+ * @count: number of bytes in @buf
+ *
  *     Sets the number of seconds to wait for the firmware.  Once
- *     this expires an error will be return to the driver and no
+ *     this expires an error will be returned to the driver and no
  *     firmware will be provided.
  *
- *     Note: zero means 'wait for ever'
- *
+ *     Note: zero means 'wait forever'.
  **/
 static ssize_t
 firmware_timeout_store(struct class *class, const char *buf, size_t count)
@@ -122,12 +125,15 @@ firmware_loading_show(struct class_device *class_dev, char *buf)
 }
 
 /**
- * firmware_loading_store: - loading control file
- * Description:
+ * firmware_loading_store - set value in the 'loading' control file
+ * @class_dev: class_device pointer
+ * @buf: buffer to scan for loading control value
+ * @count: number of bytes in @buf
+ *
  *     The relevant values are:
  *
  *      1: Start a load, discarding any previous partial load.
- *      0: Conclude the load and handle the data to the driver code.
+ *      0: Conclude the load and hand the data to the driver code.
  *     -1: Conclude the load with an error and discard any written data.
  **/
 static ssize_t
@@ -200,6 +206,7 @@ out:
        up(&fw_lock);
        return ret_count;
 }
+
 static int
 fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
 {
@@ -226,11 +233,13 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
 }
 
 /**
- * firmware_data_write:
- *
- * Description:
+ * firmware_data_write - write method for firmware
+ * @kobj: kobject for the class_device
+ * @buffer: buffer being written
+ * @offset: buffer offset for write in total data store area
+ * @count: buffer size
  *
- *     Data written to the 'data' attribute will be later handled to
+ *     Data written to the 'data' attribute will be later handed to
  *     the driver as a firmware image.
  **/
 static ssize_t
@@ -263,6 +272,7 @@ out:
        up(&fw_lock);
        return retval;
 }
+
 static struct bin_attribute firmware_attr_data_tmpl = {
        .attr = {.name = "data", .mode = 0644, .owner = THIS_MODULE},
        .size = 0,
@@ -300,9 +310,9 @@ fw_register_class_device(struct class_device **class_dev_p,
                         const char *fw_name, struct device *device)
 {
        int retval;
-       struct firmware_priv *fw_priv = kmalloc(sizeof (struct firmware_priv),
+       struct firmware_priv *fw_priv = kzalloc(sizeof(*fw_priv),
                                                GFP_KERNEL);
-       struct class_device *class_dev = kmalloc(sizeof (struct class_device),
+       struct class_device *class_dev = kzalloc(sizeof(*class_dev),
                                                 GFP_KERNEL);
 
        *class_dev_p = NULL;
@@ -312,8 +322,6 @@ fw_register_class_device(struct class_device **class_dev_p,
                retval = -ENOMEM;
                goto error_kfree;
        }
-       memset(fw_priv, 0, sizeof (*fw_priv));
-       memset(class_dev, 0, sizeof (*class_dev));
 
        init_completion(&fw_priv->completion);
        fw_priv->attr_data = firmware_attr_data_tmpl;
@@ -344,7 +352,7 @@ error_kfree:
 
 static int
 fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
-                     const char *fw_name, struct device *device)
+                     const char *fw_name, struct device *device, int hotplug)
 {
        struct class_device *class_dev;
        struct firmware_priv *fw_priv;
@@ -376,7 +384,10 @@ fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
                goto error_unreg;
        }
 
-       set_bit(FW_STATUS_READY, &fw_priv->status);
+       if (hotplug)
+                set_bit(FW_STATUS_READY, &fw_priv->status);
+        else
+                set_bit(FW_STATUS_READY_NOHOTPLUG, &fw_priv->status);
        *class_dev_p = class_dev;
        goto out;
 
@@ -386,21 +397,9 @@ out:
        return retval;
 }
 
-/**
- * request_firmware: - request firmware to hotplug and wait for it
- * Description:
- *     @firmware will be used to return a firmware image by the name
- *     of @name for device @device.
- *
- *     Should be called from user context where sleeping is allowed.
- *
- *     @name will be use as $FIRMWARE in the hotplug environment and
- *     should be distinctive enough not to be confused with any other
- *     firmware image for this or any other device.
- **/
-int
-request_firmware(const struct firmware **firmware_p, const char *name,
-                struct device *device)
+static int
+_request_firmware(const struct firmware **firmware_p, const char *name,
+                struct device *device, int hotplug)
 {
        struct class_device *class_dev;
        struct firmware_priv *fw_priv;
@@ -410,31 +409,33 @@ request_firmware(const struct firmware **firmware_p, const char *name,
        if (!firmware_p)
                return -EINVAL;
 
-       *firmware_p = firmware = kmalloc(sizeof (struct firmware), GFP_KERNEL);
+       *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
        if (!firmware) {
                printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n",
                       __FUNCTION__);
                retval = -ENOMEM;
                goto out;
        }
-       memset(firmware, 0, sizeof (*firmware));
 
-       retval = fw_setup_class_device(firmware, &class_dev, name, device);
+       retval = fw_setup_class_device(firmware, &class_dev, name, device,
+               hotplug);
        if (retval)
                goto error_kfree_fw;
 
        fw_priv = class_get_devdata(class_dev);
 
-       if (loading_timeout > 0) {
-               fw_priv->timeout.expires = jiffies + loading_timeout * HZ;
-               add_timer(&fw_priv->timeout);
-       }
-
-       kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
-       wait_for_completion(&fw_priv->completion);
-       set_bit(FW_STATUS_DONE, &fw_priv->status);
+       if (hotplug) {
+               if (loading_timeout > 0) {
+                       fw_priv->timeout.expires = jiffies + loading_timeout * HZ;
+                       add_timer(&fw_priv->timeout);
+               }
 
-       del_timer_sync(&fw_priv->timeout);
+               kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
+               wait_for_completion(&fw_priv->completion);
+               set_bit(FW_STATUS_DONE, &fw_priv->status);
+               del_timer_sync(&fw_priv->timeout);
+       } else
+               wait_for_completion(&fw_priv->completion);
 
        down(&fw_lock);
        if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) {
@@ -454,8 +455,32 @@ out:
        return retval;
 }
 
+/**
+ * request_firmware: - request firmware to hotplug and wait for it
+ * @firmware_p: pointer to firmware image
+ * @name: name of firmware file
+ * @device: device for which firmware is being loaded
+ *
+ *      @firmware_p will be used to return a firmware image by the name
+ *      of @name for device @device.
+ *
+ *      Should be called from user context where sleeping is allowed.
+ *
+ *      @name will be used as $FIRMWARE in the hotplug environment and
+ *      should be distinctive enough not to be confused with any other
+ *      firmware image for this or any other device.
+ **/
+int
+request_firmware(const struct firmware **firmware_p, const char *name,
+                 struct device *device)
+{
+        int hotplug = 1;
+        return _request_firmware(firmware_p, name, device, hotplug);
+}
+
 /**
  * release_firmware: - release the resource associated with a firmware image
+ * @fw: firmware resource to release
  **/
 void
 release_firmware(const struct firmware *fw)
@@ -468,8 +493,10 @@ release_firmware(const struct firmware *fw)
 
 /**
  * register_firmware: - provide a firmware image for later usage
+ * @name: name of firmware image file
+ * @data: buffer pointer for the firmware image
+ * @size: size of the data buffer area
  *
- * Description:
  *     Make sure that @data will be available by requesting firmware @name.
  *
  *     Note: This will not be possible until some kind of persistence
@@ -491,6 +518,7 @@ struct firmware_work {
        struct device *device;
        void *context;
        void (*cont)(const struct firmware *fw, void *context);
+       int hotplug;
 };
 
 static int
@@ -503,7 +531,8 @@ request_firmware_work_func(void *arg)
                return 0;
        }
        daemonize("%s/%s", "firmware", fw_work->name);
-       request_firmware(&fw, fw_work->name, fw_work->device);
+       _request_firmware(&fw, fw_work->name, fw_work->device,
+               fw_work->hotplug);
        fw_work->cont(fw, fw_work->context);
        release_firmware(fw);
        module_put(fw_work->module);
@@ -512,22 +541,23 @@ request_firmware_work_func(void *arg)
 }
 
 /**
- * request_firmware_nowait:
+ * request_firmware_nowait: asynchronous version of request_firmware
+ * @module: module requesting the firmware
+ * @hotplug: invokes hotplug event to copy the firmware image if this flag
+ *     is non-zero else the firmware copy must be done manually.
+ * @name: name of firmware file
+ * @device: device for which firmware is being loaded
+ * @context: will be passed over to @cont, and
+ *     @fw may be %NULL if firmware request fails.
+ * @cont: function will be called asynchronously when the firmware
+ *     request is over.
  *
- * Description:
  *     Asynchronous variant of request_firmware() for contexts where
  *     it is not possible to sleep.
- *
- *     @cont will be called asynchronously when the firmware request is over.
- *
- *     @context will be passed over to @cont.
- *
- *     @fw may be %NULL if firmware request fails.
- *
  **/
 int
 request_firmware_nowait(
-       struct module *module,
+       struct module *module, int hotplug,
        const char *name, struct device *device, void *context,
        void (*cont)(const struct firmware *fw, void *context))
 {
@@ -548,6 +578,7 @@ request_firmware_nowait(
                .device = device,
                .context = context,
                .cont = cont,
+               .hotplug = hotplug,
        };
 
        ret = kernel_thread(request_firmware_work_func, fw_work,