driver-core: do not register a driver with bus_type not registered
[safe/jmp/linux-2.6] / drivers / base / firmware_class.c
index 0e51148..44699d9 100644 (file)
@@ -49,6 +49,14 @@ struct firmware_priv {
        struct timer_list timeout;
 };
 
+#ifdef CONFIG_FW_LOADER
+extern struct builtin_fw __start_builtin_fw[];
+extern struct builtin_fw __end_builtin_fw[];
+#else /* Module case. Avoid ifdefs later; it'll all optimise out */
+static struct builtin_fw *__start_builtin_fw;
+static struct builtin_fw *__end_builtin_fw;
+#endif
+
 static void
 fw_load_abort(struct firmware_priv *fw_priv)
 {
@@ -88,19 +96,14 @@ static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store);
 
 static void fw_dev_release(struct device *dev);
 
-static int firmware_uevent(struct device *dev, char **envp, int num_envp,
-                          char *buffer, int buffer_size)
+static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
        struct firmware_priv *fw_priv = dev_get_drvdata(dev);
-       int i = 0, len = 0;
 
-       if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
-                          "FIRMWARE=%s", fw_priv->fw_id))
+       if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->fw_id))
                return -ENOMEM;
-       if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
-                          "TIMEOUT=%i", loading_timeout))
+       if (add_uevent_var(env, "TIMEOUT=%i", loading_timeout))
                return -ENOMEM;
-       envp[i] = NULL;
 
        return 0;
 }
@@ -161,8 +164,7 @@ static ssize_t firmware_loading_store(struct device *dev,
                }
                /* fallthrough */
        default:
-               printk(KERN_ERR "%s: unexpected value (%d)\n", __FUNCTION__,
-                      loading);
+               dev_err(dev, "%s: unexpected value (%d)\n", __func__, loading);
                /* fallthrough */
        case -1:
                fw_load_abort(fw_priv);
@@ -175,13 +177,13 @@ static ssize_t firmware_loading_store(struct device *dev,
 static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store);
 
 static ssize_t
-firmware_data_read(struct kobject *kobj,
+firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr,
                   char *buffer, loff_t offset, size_t count)
 {
        struct device *dev = to_dev(kobj);
        struct firmware_priv *fw_priv = dev_get_drvdata(dev);
        struct firmware *fw;
-       ssize_t ret_count = count;
+       ssize_t ret_count;
 
        mutex_lock(&fw_lock);
        fw = fw_priv->fw;
@@ -189,14 +191,8 @@ firmware_data_read(struct kobject *kobj,
                ret_count = -ENODEV;
                goto out;
        }
-       if (offset > fw->size) {
-               ret_count = 0;
-               goto out;
-       }
-       if (offset + ret_count > fw->size)
-               ret_count = fw->size - offset;
-
-       memcpy(buffer, fw->data + offset, ret_count);
+       ret_count = memory_read_from_buffer(buffer, count, &offset,
+                                               fw->data, fw->size);
 out:
        mutex_unlock(&fw_lock);
        return ret_count;
@@ -214,7 +210,7 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
        new_size = ALIGN(min_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\n", __func__);
                /* Make sure that we don't keep incomplete data */
                fw_load_abort(fw_priv);
                return -ENOMEM;
@@ -232,6 +228,7 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
 /**
  * firmware_data_write - write method for firmware
  * @kobj: kobject for the device
+ * @bin_attr: bin_attr structure
  * @buffer: buffer being written
  * @offset: buffer offset for write in total data store area
  * @count: buffer size
@@ -240,7 +237,7 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
  *     the driver as a firmware image.
  **/
 static ssize_t
-firmware_data_write(struct kobject *kobj,
+firmware_data_write(struct kobject *kobj, struct bin_attribute *bin_attr,
                    char *buffer, loff_t offset, size_t count)
 {
        struct device *dev = to_dev(kobj);
@@ -261,7 +258,7 @@ firmware_data_write(struct kobject *kobj,
        if (retval)
                goto out;
 
-       memcpy(fw->data + offset, buffer, count);
+       memcpy((u8 *)fw->data + offset, buffer, count);
 
        fw->size = max_t(size_t, offset + count, fw->size);
        retval = count;
@@ -294,12 +291,6 @@ firmware_class_timeout(u_long data)
        fw_load_abort(fw_priv);
 }
 
-static inline void fw_setup_device_id(struct device *f_dev, struct device *dev)
-{
-       /* XXX warning we should watch out for name collisions */
-       strlcpy(f_dev->bus_id, dev->bus_id, BUS_ID_SIZE);
-}
-
 static int fw_register_device(struct device **dev_p, const char *fw_name,
                              struct device *device)
 {
@@ -311,7 +302,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name,
        *dev_p = NULL;
 
        if (!fw_priv || !f_dev) {
-               printk(KERN_ERR "%s: kmalloc failed\n", __FUNCTION__);
+               dev_err(device, "%s: kmalloc failed\n", __func__);
                retval = -ENOMEM;
                goto error_kfree;
        }
@@ -324,15 +315,14 @@ static int fw_register_device(struct device **dev_p, const char *fw_name,
        fw_priv->timeout.data = (u_long) fw_priv;
        init_timer(&fw_priv->timeout);
 
-       fw_setup_device_id(f_dev, device);
+       dev_set_name(f_dev, dev_name(device));
        f_dev->parent = device;
        f_dev->class = &firmware_class;
        dev_set_drvdata(f_dev, fw_priv);
        f_dev->uevent_suppress = 1;
        retval = device_register(f_dev);
        if (retval) {
-               printk(KERN_ERR "%s: device_register failed\n",
-                      __FUNCTION__);
+               dev_err(device, "%s: device_register failed\n", __func__);
                goto error_kfree;
        }
        *dev_p = f_dev;
@@ -365,15 +355,13 @@ static int fw_setup_device(struct firmware *fw, struct device **dev_p,
        fw_priv->fw = fw;
        retval = sysfs_create_bin_file(&f_dev->kobj, &fw_priv->attr_data);
        if (retval) {
-               printk(KERN_ERR "%s: sysfs_create_bin_file failed\n",
-                      __FUNCTION__);
+               dev_err(device, "%s: sysfs_create_bin_file failed\n", __func__);
                goto error_unreg;
        }
 
        retval = device_create_file(f_dev, &dev_attr_loading);
        if (retval) {
-               printk(KERN_ERR "%s: device_create_file failed\n",
-                      __FUNCTION__);
+               dev_err(device, "%s: device_create_file failed\n", __func__);
                goto error_unreg;
        }
 
@@ -395,6 +383,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
        struct device *f_dev;
        struct firmware_priv *fw_priv;
        struct firmware *firmware;
+       struct builtin_fw *builtin;
        int retval;
 
        if (!firmware_p)
@@ -402,12 +391,26 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
 
        *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
        if (!firmware) {
-               printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n",
-                      __FUNCTION__);
+               dev_err(device, "%s: kmalloc(struct firmware) failed\n",
+                       __func__);
                retval = -ENOMEM;
                goto out;
        }
 
+       for (builtin = __start_builtin_fw; builtin != __end_builtin_fw;
+            builtin++) {
+               if (strcmp(name, builtin->name))
+                       continue;
+               dev_info(device, "firmware: using built-in firmware %s\n",
+                        name);
+               firmware->size = builtin->size;
+               firmware->data = builtin->data;
+               return 0;
+       }
+
+       if (uevent)
+               dev_info(device, "firmware: requesting %s\n", name);
+
        retval = fw_setup_device(firmware, &f_dev, name, device, uevent);
        if (retval)
                goto error_kfree_fw;
@@ -475,8 +478,16 @@ request_firmware(const struct firmware **firmware_p, const char *name,
 void
 release_firmware(const struct firmware *fw)
 {
+       struct builtin_fw *builtin;
+
        if (fw) {
+               for (builtin = __start_builtin_fw; builtin != __end_builtin_fw;
+                    builtin++) {
+                       if (fw->data == builtin->data)
+                               goto free_fw;
+               }
                vfree(fw->data);
+       free_fw:
                kfree(fw);
        }
 }
@@ -574,13 +585,13 @@ firmware_class_init(void)
        int error;
        error = class_register(&firmware_class);
        if (error) {
-               printk(KERN_ERR "%s: class_register failed\n", __FUNCTION__);
+               printk(KERN_ERR "%s: class_register failed\n", __func__);
                return error;
        }
        error = class_create_file(&firmware_class, &class_attr_timeout);
        if (error) {
                printk(KERN_ERR "%s: class_create_file failed\n",
-                      __FUNCTION__);
+                      __func__);
                class_unregister(&firmware_class);
        }
        return error;