From 5685ad5b29934e09dd9746f8553066f8288d4dff Mon Sep 17 00:00:00 2001 From: "Hans J. Koch" Date: Thu, 10 Jun 2010 01:12:32 +0200 Subject: uio: Remove IRQF_DISABLED flag from uio_pdrv_genirq.c Remove IRQF_DISABLED flag since it is deprecated and a no-op in the current kernel. Signed-off-by: Hans J. Koch Signed-off-by: Greg Kroah-Hartman --- drivers/uio/uio_pdrv_genirq.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c index 61e569df2bb..7174d518b8a 100644 --- a/drivers/uio/uio_pdrv_genirq.c +++ b/drivers/uio/uio_pdrv_genirq.c @@ -155,7 +155,6 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev) * Interrupt sharing is not supported. */ - uioinfo->irq_flags |= IRQF_DISABLED; uioinfo->handler = uio_pdrv_genirq_handler; uioinfo->irqcontrol = uio_pdrv_genirq_irqcontrol; uioinfo->open = uio_pdrv_genirq_open; -- cgit v1.2.3 From 62c867791f7b9feb2f6c2ca60e8a246d0c810ad9 Mon Sep 17 00:00:00 2001 From: "Hans J. Koch" Date: Thu, 10 Jun 2010 01:15:49 +0200 Subject: uio: Remove IRQF_DISABLED from uio_sercos3.c Remove IRQF_DISABLED since it is deprecated and a no-op in the current kernel. Signed-off-by: Hans J. Koch Acked-by: John Ogness Signed-off-by: Greg Kroah-Hartman --- drivers/uio/uio_sercos3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/uio/uio_sercos3.c b/drivers/uio/uio_sercos3.c index 3d461cd73e6..a187fa14c5c 100644 --- a/drivers/uio/uio_sercos3.c +++ b/drivers/uio/uio_sercos3.c @@ -154,7 +154,7 @@ static int __devinit sercos3_pci_probe(struct pci_dev *dev, info->name = "Sercos_III_PCI"; info->version = "0.0.1"; info->irq = dev->irq; - info->irq_flags = IRQF_DISABLED | IRQF_SHARED; + info->irq_flags = IRQF_SHARED; info->handler = sercos3_handler; info->irqcontrol = sercos3_irqcontrol; -- cgit v1.2.3 From 14ec5394827eea8df7bbf14775c52fc48fc97a40 Mon Sep 17 00:00:00 2001 From: "Hans J. Koch" Date: Thu, 10 Jun 2010 01:18:08 +0200 Subject: uio: Remove IRQF_DISABLED flag from uio_cif.c Remove IRQF_DISABLED since it is deprecated and a no-op in the current kernel. Signed-off-by: Hans J. Koch Signed-off-by: Greg Kroah-Hartman --- drivers/uio/uio_cif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/uio/uio_cif.c b/drivers/uio/uio_cif.c index 371f87f8bc2..a8ea2f19a0c 100644 --- a/drivers/uio/uio_cif.c +++ b/drivers/uio/uio_cif.c @@ -79,7 +79,7 @@ static int __devinit hilscher_pci_probe(struct pci_dev *dev, } info->version = "0.0.1"; info->irq = dev->irq; - info->irq_flags = IRQF_DISABLED | IRQF_SHARED; + info->irq_flags = IRQF_SHARED; info->handler = hilscher_handler; if (uio_register_device(&dev->dev, info)) -- cgit v1.2.3 From 94f17cd7887ca681ea88fda1fd9bf65c0ca161f0 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 7 Jun 2010 12:57:12 +0100 Subject: hotplug: Support kernel/hotplug sysctl variable when !CONFIG_NET The kernel/hotplug sysctl variable (/proc/sys/kernel/hotplug file) was made conditional on CONFIG_NET by commit f743ca5e10f4145e0b3e6d11b9b46171e16af7ce (applied in 2.6.18) to fix problems with undefined references in 2.6.16 when CONFIG_HOTPLUG=y && !CONFIG_NET, but this restriction is no longer needed. This patch makes the kernel/hotplug sysctl variable depend only on CONFIG_HOTPLUG. Signed-off-by: Ian Abbott Acked-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- kernel/sysctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index d24f761f487..f73da1c857e 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -562,7 +562,7 @@ static struct ctl_table kern_table[] = { .extra2 = &one, }, #endif -#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET) +#ifdef CONFIG_HOTPLUG { .procname = "hotplug", .data = &uevent_helper, -- cgit v1.2.3 From ed1d218c95c6846416ddb39085b20a5b3c0872e4 Mon Sep 17 00:00:00 2001 From: Marin Mitov Date: Mon, 31 May 2010 13:03:04 +0300 Subject: Driver core: internal struct dma_coherent_mem, change type of a member. struct dma_coherent_mem in drivers/base/dma-coherent.c has member 'device_base' that is of type u32, but is assigned value of type dma_addr_t, which may be 64 bits for x86_64. Change the type to dma_addr_t. Signed-off-by: Marin Mitov Signed-off-by: Greg Kroah-Hartman --- drivers/base/dma-coherent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c index d4d8ce53886..f369e279598 100644 --- a/drivers/base/dma-coherent.c +++ b/drivers/base/dma-coherent.c @@ -8,7 +8,7 @@ struct dma_coherent_mem { void *virt_base; - u32 device_base; + dma_addr_t device_base; int size; int flags; unsigned long *bitmap; -- cgit v1.2.3 From cc7447a5fa92759b0856d6a83ba2539c6a94e67e Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 16 Jun 2010 11:44:18 +0200 Subject: Driver core: Drop __must_check from bus_for_each_drv() There is little rationale for marking bus_for_each_drv() __must_check. It is more of an iteration helper than a real function. You don't know in advance which callback it will be used on, so you have no clue how important it can be to check the returned value. In practice, this helper function can be used for best-effort tasks. As a matter of fact, bus_for_each_dev() is not marked __must_check. So remove it from bus_for_each_drv() as well. This is the same that was done back in October 2006 by Russell King for device_for_each_child(), for exactly the same reasons. Signed-off-by: Jean Delvare Cc: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- include/linux/device.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/linux/device.h b/include/linux/device.h index 6a8276f683b..ddffdf7da39 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -84,9 +84,8 @@ struct device *bus_find_device_by_name(struct bus_type *bus, struct device *start, const char *name); -int __must_check bus_for_each_drv(struct bus_type *bus, - struct device_driver *start, void *data, - int (*fn)(struct device_driver *, void *)); +int bus_for_each_drv(struct bus_type *bus, struct device_driver *start, + void *data, int (*fn)(struct device_driver *, void *)); void bus_sort_breadthfirst(struct bus_type *bus, int (*compare)(const struct device *a, -- cgit v1.2.3 From 0983ca2d0f0ff645bc86899aefb936cffb314839 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 4 Jun 2010 00:54:37 -0700 Subject: firmware loader: use statically initialized data attribute There is no reason why we are using a template for binary attribute and copying it into per-firmware data before registering. Using the original works as well. Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 3f093b0dd21..fb29c64ebec 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -87,7 +87,6 @@ static DEFINE_MUTEX(fw_lock); struct firmware_priv { struct completion completion; - struct bin_attribute attr_data; struct firmware *fw; unsigned long status; struct page **pages; @@ -420,8 +419,8 @@ out: return retval; } -static struct bin_attribute firmware_attr_data_tmpl = { - .attr = {.name = "data", .mode = 0644}, +static struct bin_attribute firmware_attr_data = { + .attr = { .name = "data", .mode = 0644 }, .size = 0, .read = firmware_data_read, .write = firmware_data_write, @@ -452,7 +451,6 @@ static int fw_register_device(struct device **dev_p, const char *fw_name, strcpy(fw_priv->fw_id, fw_name); init_completion(&fw_priv->completion); - fw_priv->attr_data = firmware_attr_data_tmpl; fw_priv->timeout.function = firmware_class_timeout; fw_priv->timeout.data = (u_long) fw_priv; init_timer(&fw_priv->timeout); @@ -498,8 +496,7 @@ static int fw_setup_device(struct firmware *fw, struct device **dev_p, fw_priv->nowait = nowait; fw_priv->fw = fw; - sysfs_bin_attr_init(&fw_priv->attr_data); - retval = sysfs_create_bin_file(&f_dev->kobj, &fw_priv->attr_data); + retval = sysfs_create_bin_file(&f_dev->kobj, &firmware_attr_data); if (retval) { dev_err(device, "%s: sysfs_create_bin_file failed\n", __func__); goto error_unreg; -- cgit v1.2.3 From f8a4bd3456b988fc73b2c291b9e01b434c8fa940 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 4 Jun 2010 00:54:43 -0700 Subject: firmware loader: embed device into firmware_priv structure Both these structures have the same lifetime rules so instead of allocating and managing them separately embed struct device into struct firmware_priv. Also make sure to delete sysfs attributes ourselves instead of expecting sysfs to clean up our mess. Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 255 ++++++++++++++++++++---------------------- 1 file changed, 122 insertions(+), 133 deletions(-) diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index fb29c64ebec..c8a44f5e058 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -93,22 +93,26 @@ struct firmware_priv { int nr_pages; int page_array_size; struct timer_list timeout; + struct device dev; bool nowait; char fw_id[]; }; -static void -fw_load_abort(struct firmware_priv *fw_priv) +static struct firmware_priv *to_firmware_priv(struct device *dev) +{ + return container_of(dev, struct firmware_priv, dev); +} + +static void fw_load_abort(struct firmware_priv *fw_priv) { set_bit(FW_STATUS_ABORT, &fw_priv->status); wmb(); complete(&fw_priv->completion); } -static ssize_t -firmware_timeout_show(struct class *class, - struct class_attribute *attr, - char *buf) +static ssize_t firmware_timeout_show(struct class *class, + struct class_attribute *attr, + char *buf) { return sprintf(buf, "%d\n", loading_timeout); } @@ -126,14 +130,14 @@ firmware_timeout_show(struct class *class, * * Note: zero means 'wait forever'. **/ -static ssize_t -firmware_timeout_store(struct class *class, - struct class_attribute *attr, - const char *buf, size_t count) +static ssize_t firmware_timeout_store(struct class *class, + struct class_attribute *attr, + const char *buf, size_t count) { loading_timeout = simple_strtol(buf, NULL, 10); if (loading_timeout < 0) loading_timeout = 0; + return count; } @@ -145,21 +149,20 @@ static struct class_attribute firmware_class_attrs[] = { static void fw_dev_release(struct device *dev) { - struct firmware_priv *fw_priv = dev_get_drvdata(dev); + struct firmware_priv *fw_priv = to_firmware_priv(dev); int i; for (i = 0; i < fw_priv->nr_pages; i++) __free_page(fw_priv->pages[i]); kfree(fw_priv->pages); kfree(fw_priv); - kfree(dev); module_put(THIS_MODULE); } static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) { - struct firmware_priv *fw_priv = dev_get_drvdata(dev); + struct firmware_priv *fw_priv = to_firmware_priv(dev); if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->fw_id)) return -ENOMEM; @@ -181,8 +184,9 @@ static struct class firmware_class = { static ssize_t firmware_loading_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct firmware_priv *fw_priv = dev_get_drvdata(dev); + struct firmware_priv *fw_priv = to_firmware_priv(dev); int loading = test_bit(FW_STATUS_LOADING, &fw_priv->status); + return sprintf(buf, "%d\n", loading); } @@ -218,7 +222,7 @@ static ssize_t firmware_loading_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct firmware_priv *fw_priv = dev_get_drvdata(dev); + struct firmware_priv *fw_priv = to_firmware_priv(dev); int loading = simple_strtol(buf, NULL, 10); int i; @@ -276,13 +280,12 @@ 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 file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, char *buffer, loff_t offset, - size_t count) +static ssize_t firmware_data_read(struct file *filp, 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_priv *fw_priv = to_firmware_priv(dev); struct firmware *fw; ssize_t ret_count; @@ -321,8 +324,7 @@ out: return ret_count; } -static int -fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) +static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) { int pages_needed = ALIGN(min_size, PAGE_SIZE) >> PAGE_SHIFT; @@ -372,13 +374,12 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) * Data written to the 'data' attribute will be later handed to * the driver as a firmware image. **/ -static ssize_t -firmware_data_write(struct file* filp, struct kobject *kobj, - struct bin_attribute *bin_attr, char *buffer, - loff_t offset, size_t count) +static ssize_t firmware_data_write(struct file *filp, 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_priv *fw_priv = to_firmware_priv(dev); struct firmware *fw; ssize_t retval; @@ -426,107 +427,96 @@ static struct bin_attribute firmware_attr_data = { .write = firmware_data_write, }; -static void -firmware_class_timeout(u_long data) +static void firmware_class_timeout(u_long data) { struct firmware_priv *fw_priv = (struct firmware_priv *) data; + fw_load_abort(fw_priv); } -static int fw_register_device(struct device **dev_p, const char *fw_name, - struct device *device) +static struct firmware_priv * +fw_create_instance(struct firmware *firmware, const char *fw_name, + struct device *device, bool uevent, bool nowait) { - int retval; - struct firmware_priv *fw_priv = - kzalloc(sizeof(*fw_priv) + strlen(fw_name) + 1 , GFP_KERNEL); - struct device *f_dev = kzalloc(sizeof(*f_dev), GFP_KERNEL); - - *dev_p = NULL; + struct firmware_priv *fw_priv; + struct device *f_dev; + int error; - if (!fw_priv || !f_dev) { + fw_priv = kzalloc(sizeof(*fw_priv) + strlen(fw_name) + 1 , GFP_KERNEL); + if (!fw_priv) { dev_err(device, "%s: kmalloc failed\n", __func__); - retval = -ENOMEM; - goto error_kfree; + error = -ENOMEM; + goto err_out; } + fw_priv->fw = firmware; + fw_priv->nowait = nowait; strcpy(fw_priv->fw_id, fw_name); init_completion(&fw_priv->completion); - fw_priv->timeout.function = firmware_class_timeout; - fw_priv->timeout.data = (u_long) fw_priv; - init_timer(&fw_priv->timeout); + setup_timer(&fw_priv->timeout, + firmware_class_timeout, (u_long) fw_priv); + f_dev = &fw_priv->dev; + + device_initialize(f_dev); dev_set_name(f_dev, "%s", dev_name(device)); f_dev->parent = device; f_dev->class = &firmware_class; - dev_set_drvdata(f_dev, fw_priv); - dev_set_uevent_suppress(f_dev, 1); - retval = device_register(f_dev); - if (retval) { - dev_err(device, "%s: device_register failed\n", __func__); - put_device(f_dev); - return retval; - } - *dev_p = f_dev; - return 0; - -error_kfree: - kfree(f_dev); - kfree(fw_priv); - return retval; -} -static int fw_setup_device(struct firmware *fw, struct device **dev_p, - const char *fw_name, struct device *device, - int uevent, bool nowait) -{ - struct device *f_dev; - struct firmware_priv *fw_priv; - int retval; - - *dev_p = NULL; - retval = fw_register_device(&f_dev, fw_name, device); - if (retval) - goto out; + dev_set_uevent_suppress(f_dev, true); /* Need to pin this module until class device is destroyed */ __module_get(THIS_MODULE); - fw_priv = dev_get_drvdata(f_dev); - - fw_priv->nowait = nowait; + error = device_add(f_dev); + if (error) { + dev_err(device, "%s: device_register failed\n", __func__); + goto err_put_dev; + } - fw_priv->fw = fw; - retval = sysfs_create_bin_file(&f_dev->kobj, &firmware_attr_data); - if (retval) { + error = device_create_bin_file(f_dev, &firmware_attr_data); + if (error) { dev_err(device, "%s: sysfs_create_bin_file failed\n", __func__); - goto error_unreg; + goto err_del_dev; } - retval = device_create_file(f_dev, &dev_attr_loading); - if (retval) { + error = device_create_file(f_dev, &dev_attr_loading); + if (error) { dev_err(device, "%s: device_create_file failed\n", __func__); - goto error_unreg; + goto err_del_bin_attr; } if (uevent) - dev_set_uevent_suppress(f_dev, 0); - *dev_p = f_dev; - goto out; + dev_set_uevent_suppress(f_dev, false); + + return fw_priv; + +err_del_bin_attr: + device_remove_bin_file(f_dev, &firmware_attr_data); +err_del_dev: + device_del(f_dev); +err_put_dev: + put_device(f_dev); +err_out: + return ERR_PTR(error); +} + +static void fw_destroy_instance(struct firmware_priv *fw_priv) +{ + struct device *f_dev = &fw_priv->dev; -error_unreg: + device_remove_file(f_dev, &dev_attr_loading); + device_remove_bin_file(f_dev, &firmware_attr_data); device_unregister(f_dev); -out: - return retval; } -static int -_request_firmware(const struct firmware **firmware_p, const char *name, - struct device *device, int uevent, bool nowait) +static int _request_firmware(const struct firmware **firmware_p, + const char *name, struct device *device, + bool uevent, bool nowait) { - struct device *f_dev; struct firmware_priv *fw_priv; struct firmware *firmware; - int retval; + int retval = 0; if (!firmware_p) return -EINVAL; @@ -547,41 +537,40 @@ _request_firmware(const struct firmware **firmware_p, const char *name, if (uevent) dev_dbg(device, "firmware: requesting %s\n", name); - retval = fw_setup_device(firmware, &f_dev, name, device, - uevent, nowait); - if (retval) - goto error_kfree_fw; - - fw_priv = dev_get_drvdata(f_dev); + fw_priv = fw_create_instance(firmware, name, device, uevent, nowait); + if (IS_ERR(fw_priv)) { + retval = PTR_ERR(fw_priv); + goto out; + } if (uevent) { - if (loading_timeout > 0) { - fw_priv->timeout.expires = jiffies + loading_timeout * HZ; - add_timer(&fw_priv->timeout); - } + if (loading_timeout > 0) + mod_timer(&fw_priv->timeout, + round_jiffies_up(jiffies + + loading_timeout * HZ)); + + kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD); + } + + wait_for_completion(&fw_priv->completion); - kobject_uevent(&f_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); + set_bit(FW_STATUS_DONE, &fw_priv->status); + del_timer_sync(&fw_priv->timeout); mutex_lock(&fw_lock); - if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) { + if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) retval = -ENOENT; - release_firmware(fw_priv->fw); - *firmware_p = NULL; - } fw_priv->fw = NULL; mutex_unlock(&fw_lock); - device_unregister(f_dev); - goto out; -error_kfree_fw: - kfree(firmware); - *firmware_p = NULL; + fw_destroy_instance(fw_priv); + out: + if (retval) { + release_firmware(firmware); + firmware_p = NULL; + } + return retval; } @@ -632,23 +621,24 @@ struct firmware_work { int uevent; }; -static int -request_firmware_work_func(void *arg) +static int request_firmware_work_func(void *arg) { struct firmware_work *fw_work = arg; const struct firmware *fw; int ret; + if (!arg) { WARN_ON(1); return 0; } - ret = _request_firmware(&fw, fw_work->name, fw_work->device, - fw_work->uevent, true); + ret = _request_firmware(&fw, fw_work->name, fw_work->device, + fw_work->uevent, true); fw_work->cont(fw, fw_work->context); module_put(fw_work->module); kfree(fw_work); + return ret; } @@ -676,34 +666,33 @@ request_firmware_nowait( void (*cont)(const struct firmware *fw, void *context)) { struct task_struct *task; - struct firmware_work *fw_work = kmalloc(sizeof (struct firmware_work), - gfp); + struct firmware_work *fw_work; + fw_work = kzalloc(sizeof (struct firmware_work), gfp); if (!fw_work) return -ENOMEM; + + fw_work->module = module; + fw_work->name = name; + fw_work->device = device; + fw_work->context = context; + fw_work->cont = cont; + fw_work->uevent = uevent; + if (!try_module_get(module)) { kfree(fw_work); return -EFAULT; } - *fw_work = (struct firmware_work) { - .module = module, - .name = name, - .device = device, - .context = context, - .cont = cont, - .uevent = uevent, - }; - task = kthread_run(request_firmware_work_func, fw_work, "firmware/%s", name); - if (IS_ERR(task)) { fw_work->cont(NULL, fw_work->context); module_put(fw_work->module); kfree(fw_work); return PTR_ERR(task); } + return 0; } -- cgit v1.2.3 From 3e61dfd8509a52d165726831c57b4c8a015d626c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 15 Jun 2010 10:47:55 +0200 Subject: Driver core: use kmemdup in platform_device_add_resources MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes platform_device_add_resources look like platform_device_add_data. Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 4d99c8bdfed..26eb69d88eb 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -191,13 +191,13 @@ int platform_device_add_resources(struct platform_device *pdev, { struct resource *r; - r = kmalloc(sizeof(struct resource) * num, GFP_KERNEL); + r = kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL); if (r) { - memcpy(r, res, sizeof(struct resource) * num); pdev->resource = r; pdev->num_resources = num; + return 0; } - return r ? 0 : -ENOMEM; + return -ENOMEM; } EXPORT_SYMBOL_GPL(platform_device_add_resources); -- cgit v1.2.3 From 44f28bdea09415d40b4d73a7668db5961362ec53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 21 Jun 2010 16:11:44 +0200 Subject: Driver core: reduce duplicated code for platform_device creation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes the two similar functions platform_device_register_simple and platform_device_register_data one line inline functions using a new generic function platform_device_register_resndata. Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- Documentation/DocBook/device-drivers.tmpl | 1 + drivers/base/platform.c | 104 ++++++++---------------------- include/linux/platform_device.h | 62 ++++++++++++++++-- 3 files changed, 85 insertions(+), 82 deletions(-) diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl index 1b2dd4fc3db..ecd35e9d441 100644 --- a/Documentation/DocBook/device-drivers.tmpl +++ b/Documentation/DocBook/device-drivers.tmpl @@ -111,6 +111,7 @@ X!Edrivers/base/attribute_container.c +!Iinclude/linux/platform_device.h !Edrivers/base/platform.c !Edrivers/base/bus.c diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 26eb69d88eb..ffcfd73fe8a 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -344,108 +344,56 @@ void platform_device_unregister(struct platform_device *pdev) EXPORT_SYMBOL_GPL(platform_device_unregister); /** - * platform_device_register_simple - add a platform-level device and its resources - * @name: base name of the device we're adding - * @id: instance id - * @res: set of resources that needs to be allocated for the device - * @num: number of resources - * - * This function creates a simple platform device that requires minimal - * resource and memory management. Canned release function freeing memory - * allocated for the device allows drivers using such devices to be - * unloaded without waiting for the last reference to the device to be - * dropped. + * platform_device_register_resndata - add a platform-level device with + * resources and platform-specific data * - * This interface is primarily intended for use with legacy drivers which - * probe hardware directly. Because such drivers create sysfs device nodes - * themselves, rather than letting system infrastructure handle such device - * enumeration tasks, they don't fully conform to the Linux driver model. - * In particular, when such drivers are built as modules, they can't be - * "hotplugged". - * - * Returns &struct platform_device pointer on success, or ERR_PTR() on error. - */ -struct platform_device *platform_device_register_simple(const char *name, - int id, - const struct resource *res, - unsigned int num) -{ - struct platform_device *pdev; - int retval; - - pdev = platform_device_alloc(name, id); - if (!pdev) { - retval = -ENOMEM; - goto error; - } - - if (num) { - retval = platform_device_add_resources(pdev, res, num); - if (retval) - goto error; - } - - retval = platform_device_add(pdev); - if (retval) - goto error; - - return pdev; - -error: - platform_device_put(pdev); - return ERR_PTR(retval); -} -EXPORT_SYMBOL_GPL(platform_device_register_simple); - -/** - * platform_device_register_data - add a platform-level device with platform-specific data * @parent: parent device for the device we're adding * @name: base name of the device we're adding * @id: instance id + * @res: set of resources that needs to be allocated for the device + * @num: number of resources * @data: platform specific data for this platform device * @size: size of platform specific data * - * This function creates a simple platform device that requires minimal - * resource and memory management. Canned release function freeing memory - * allocated for the device allows drivers using such devices to be - * unloaded without waiting for the last reference to the device to be - * dropped. - * * Returns &struct platform_device pointer on success, or ERR_PTR() on error. */ -struct platform_device *platform_device_register_data( +struct platform_device *platform_device_register_resndata( struct device *parent, const char *name, int id, + const struct resource *res, unsigned int num, const void *data, size_t size) { + int ret = -ENOMEM; struct platform_device *pdev; - int retval; pdev = platform_device_alloc(name, id); - if (!pdev) { - retval = -ENOMEM; - goto error; - } + if (!pdev) + goto err; pdev->dev.parent = parent; - if (size) { - retval = platform_device_add_data(pdev, data, size); - if (retval) - goto error; + if (res) { + ret = platform_device_add_resources(pdev, res, num); + if (ret) + goto err; } - retval = platform_device_add(pdev); - if (retval) - goto error; + if (data) { + ret = platform_device_add_data(pdev, data, size); + if (ret) + goto err; + } - return pdev; + ret = platform_device_add(pdev); + if (ret) { +err: + platform_device_put(pdev); + return ERR_PTR(ret); + } -error: - platform_device_put(pdev); - return ERR_PTR(retval); + return pdev; } -EXPORT_SYMBOL_GPL(platform_device_register_data); +EXPORT_SYMBOL_GPL(platform_device_register_resndata); static int platform_drv_probe(struct device *_dev) { diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 5417944d368..d7ecad0093b 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -43,10 +43,64 @@ extern struct resource *platform_get_resource_byname(struct platform_device *, u extern int platform_get_irq_byname(struct platform_device *, const char *); extern int platform_add_devices(struct platform_device **, int); -extern struct platform_device *platform_device_register_simple(const char *, int id, - const struct resource *, unsigned int); -extern struct platform_device *platform_device_register_data(struct device *, - const char *, int, const void *, size_t); +extern struct platform_device *platform_device_register_resndata( + struct device *parent, const char *name, int id, + const struct resource *res, unsigned int num, + const void *data, size_t size); + +/** + * platform_device_register_simple - add a platform-level device and its resources + * @name: base name of the device we're adding + * @id: instance id + * @res: set of resources that needs to be allocated for the device + * @num: number of resources + * + * This function creates a simple platform device that requires minimal + * resource and memory management. Canned release function freeing memory + * allocated for the device allows drivers using such devices to be + * unloaded without waiting for the last reference to the device to be + * dropped. + * + * This interface is primarily intended for use with legacy drivers which + * probe hardware directly. Because such drivers create sysfs device nodes + * themselves, rather than letting system infrastructure handle such device + * enumeration tasks, they don't fully conform to the Linux driver model. + * In particular, when such drivers are built as modules, they can't be + * "hotplugged". + * + * Returns &struct platform_device pointer on success, or ERR_PTR() on error. + */ +static inline struct platform_device *platform_device_register_simple( + const char *name, int id, + const struct resource *res, unsigned int num) +{ + return platform_device_register_resndata(NULL, name, id, + res, num, NULL, 0); +} + +/** + * platform_device_register_data - add a platform-level device with platform-specific data + * @parent: parent device for the device we're adding + * @name: base name of the device we're adding + * @id: instance id + * @data: platform specific data for this platform device + * @size: size of platform specific data + * + * This function creates a simple platform device that requires minimal + * resource and memory management. Canned release function freeing memory + * allocated for the device allows drivers using such devices to be + * unloaded without waiting for the last reference to the device to be + * dropped. + * + * Returns &struct platform_device pointer on success, or ERR_PTR() on error. + */ +static inline struct platform_device *platform_device_register_data( + struct device *parent, const char *name, int id, + const void *data, size_t size) +{ + return platform_device_register_resndata(parent, name, id, + NULL, 0, data, size); +} extern struct platform_device *platform_device_alloc(const char *name, int id); extern int platform_device_add_resources(struct platform_device *pdev, -- cgit v1.2.3 From 737a3bb9416ce2a7c7a4170852473a4fcc9c67e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 21 Jun 2010 16:11:45 +0200 Subject: Driver core: move platform device creation helpers to .init.text (if MODULE=n) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Platform devices should only be called by init code, so it should be possible to move creation helpers to .init.text -- at least if modules are disabled. Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index ffcfd73fe8a..1bb8faaa443 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -357,7 +357,7 @@ EXPORT_SYMBOL_GPL(platform_device_unregister); * * Returns &struct platform_device pointer on success, or ERR_PTR() on error. */ -struct platform_device *platform_device_register_resndata( +struct platform_device *__init_or_module platform_device_register_resndata( struct device *parent, const char *name, int id, const struct resource *res, unsigned int num, -- cgit v1.2.3 From 3317fad5e9c741e758707879c68e20de2cb08f87 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 25 Jun 2010 17:55:11 +0900 Subject: firmware: Update hotplug script Update the in-kernel hotplug example script to work properly with recent kernels. Without this fix the script may load the firmware twice - both at "add" and "remove" time. The second load only triggers in the case when multiple firmware images are used. A good example is the b43 driver which does not work properly without this fix. Signed-off-by: Magnus Damm Signed-off-by: Greg Kroah-Hartman --- Documentation/firmware_class/hotplug-script | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Documentation/firmware_class/hotplug-script b/Documentation/firmware_class/hotplug-script index 1990130f2ab..8143a950b60 100644 --- a/Documentation/firmware_class/hotplug-script +++ b/Documentation/firmware_class/hotplug-script @@ -6,11 +6,12 @@ HOTPLUG_FW_DIR=/usr/lib/hotplug/firmware/ -echo 1 > /sys/$DEVPATH/loading -cat $HOTPLUG_FW_DIR/$FIRMWARE > /sys/$DEVPATH/data -echo 0 > /sys/$DEVPATH/loading - -# To cancel the load in case of error: -# -# echo -1 > /sys/$DEVPATH/loading -# +if [ "$SUBSYSTEM" == "firmware" -a "$ACTION" == "add" ]; then + if [ -f $HOTPLUG_FW_DIR/$FIRMWARE ]; then + echo 1 > /sys/$DEVPATH/loading + cat $HOTPLUG_FW_DIR/$FIRMWARE > /sys/$DEVPATH/data + echo 0 > /sys/$DEVPATH/loading + else + echo -1 > /sys/$DEVPATH/loading + fi +fi -- cgit v1.2.3 From 49c19400f60bbe362202d7e7b3e68cc66040d0fa Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 2 Jul 2010 16:54:05 +0200 Subject: sysfs: sysfs_chmod_file's attr can be const sysfs_chmod_file doesn't change the attribute it operates on, so this attribute can be marked const. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/file.c | 3 ++- include/linux/sysfs.h | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 1beaa739d0a..1b27b5688f6 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -593,7 +593,8 @@ EXPORT_SYMBOL_GPL(sysfs_add_file_to_group); * @mode: file permissions. * */ -int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) +int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr, + mode_t mode) { struct sysfs_dirent *sd; struct iattr newattrs; diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index f2694eb4dd3..8bf06b64487 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -136,8 +136,8 @@ int __must_check sysfs_create_file(struct kobject *kobj, const struct attribute *attr); int __must_check sysfs_create_files(struct kobject *kobj, const struct attribute **attr); -int __must_check sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, - mode_t mode); +int __must_check sysfs_chmod_file(struct kobject *kobj, + const struct attribute *attr, mode_t mode); void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr); void sysfs_remove_files(struct kobject *kobj, const struct attribute **attr); @@ -225,7 +225,7 @@ static inline int sysfs_create_files(struct kobject *kobj, } static inline int sysfs_chmod_file(struct kobject *kobj, - struct attribute *attr, mode_t mode) + const struct attribute *attr, mode_t mode) { return 0; } -- cgit v1.2.3 From 5b232f753a842fa66eab86e51dc76e3929d853af Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 1 Jul 2010 10:35:07 +0800 Subject: dmi-id: fix a memory leak in dmi_id_init error path This patch adds a missing kfree(dmi_dev) in dmi_id_init error path. Signed-off-by: Axel Lin Acked-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/dmi-id.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/dmi-id.c b/drivers/firmware/dmi-id.c index a777a35381d..94a58a082b9 100644 --- a/drivers/firmware/dmi-id.c +++ b/drivers/firmware/dmi-id.c @@ -229,10 +229,12 @@ static int __init dmi_id_init(void) ret = device_register(dmi_dev); if (ret) - goto fail_class_unregister; + goto fail_free_dmi_dev; return 0; +fail_free_dmi_dev: + kfree(dmi_dev); fail_class_unregister: class_unregister(&dmi_class); -- cgit v1.2.3 From e3ed249af8cb2f73fc6ef5494d2ddef43fb0ff19 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 5 Jul 2010 09:35:47 +0800 Subject: dcdbas: remove a redundant smi_data_buf_free in dcdbas_exit smi_data_buf_free is called twice in current implementation. The second call simply return because smi_data_buf is set to NULL in first call. This patch removes the second smi_data_buf_free call. Signed-off-by: Axel Lin Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/dcdbas.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c index aa9bc9e980e..69ad529d92f 100644 --- a/drivers/firmware/dcdbas.c +++ b/drivers/firmware/dcdbas.c @@ -634,9 +634,6 @@ static void __exit dcdbas_exit(void) * before platform_device_unregister */ unregister_reboot_notifier(&dcdbas_reboot_nb); - smi_data_buf_free(); - platform_device_unregister(dcdbas_pdev); - platform_driver_unregister(&dcdbas_driver); /* * We have to free the buffer here instead of dcdbas_remove @@ -645,6 +642,8 @@ static void __exit dcdbas_exit(void) * released. */ smi_data_buf_free(); + platform_device_unregister(dcdbas_pdev); + platform_driver_unregister(&dcdbas_driver); } module_init(dcdbas_init); -- cgit v1.2.3 From 30a69000a4ba9cf49e8b826431847cc80881b59b Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 20 Jul 2010 15:22:05 -0700 Subject: sysfs: fix discrepancies between implementation and documentation Fix all discrepancies I know of between the sysfs implementation and its documentation. Signed-off-by: Bart Van Assche Cc: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- Documentation/filesystems/sysfs.txt | 44 +++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt index 931c806642c..d78ed0bb275 100644 --- a/Documentation/filesystems/sysfs.txt +++ b/Documentation/filesystems/sysfs.txt @@ -4,7 +4,7 @@ sysfs - _The_ filesystem for exporting kernel objects. Patrick Mochel Mike Murphy -Revised: 22 February 2009 +Revised: 10 July 2010 Original: 10 January 2003 @@ -124,7 +124,7 @@ show and store methods of the attribute owners. struct sysfs_ops { ssize_t (*show)(struct kobject *, struct attribute *, char *); - ssize_t (*store)(struct kobject *, struct attribute *, const char *); + ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t); }; [ Subsystems should have already defined a struct kobj_type as a @@ -139,18 +139,22 @@ calls the associated methods. To illustrate: +#define to_dev(obj) container_of(obj, struct device, kobj) #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) -#define to_dev(d) container_of(d, struct device, kobj) -static ssize_t -dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) +static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr, + char *buf) { - struct device_attribute * dev_attr = to_dev_attr(attr); - struct device * dev = to_dev(kobj); - ssize_t ret = 0; + struct device_attribute *dev_attr = to_dev_attr(attr); + struct device *dev = to_dev(kobj); + ssize_t ret = -EIO; if (dev_attr->show) - ret = dev_attr->show(dev, buf); + ret = dev_attr->show(dev, dev_attr, buf); + if (ret >= (ssize_t)PAGE_SIZE) { + print_symbol("dev_attr_show: %s returned bad count\n", + (unsigned long)dev_attr->show); + } return ret; } @@ -163,10 +167,9 @@ To read or write attributes, show() or store() methods must be specified when declaring the attribute. The method types should be as simple as those defined for device attributes: -ssize_t (*show)(struct device * dev, struct device_attribute * attr, - char * buf); -ssize_t (*store)(struct device * dev, struct device_attribute * attr, - const char * buf); +ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf); +ssize_t (*store)(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count); IOW, they should take only an object, an attribute, and a buffer as parameters. @@ -209,8 +212,8 @@ Other notes: - show() should always use snprintf(). -- store() should return the number of bytes used from the buffer. This - can be done using strlen(). +- store() should return the number of bytes used from the buffer. If the + entire buffer has been used, just return the count argument. - show() or store() can always return errors. If a bad value comes through, be sure to return an error. @@ -223,15 +226,18 @@ Other notes: A very simple (and naive) implementation of a device attribute is: -static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t show_name(struct device *dev, struct device_attribute *attr, + char *buf) { return snprintf(buf, PAGE_SIZE, "%s\n", dev->name); } -static ssize_t store_name(struct device * dev, const char * buf) +static ssize_t store_name(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { - sscanf(buf, "%20s", dev->name); - return strnlen(buf, PAGE_SIZE); + snprintf(dev->name, sizeof(dev->name), "%.*s", + (int)min(count, sizeof(dev->name) - 1), buf); + return count; } static DEVICE_ATTR(name, S_IRUGO, show_name, store_name); -- cgit v1.2.3 From a5307032718b1e90e6d07008d7fd44d1446db7d7 Mon Sep 17 00:00:00 2001 From: Ira Weiny Date: Thu, 15 Jul 2010 11:34:44 -0700 Subject: sysfs: Fix one more signature discrepancy between sysfs implementation and docs. Signed-off-by: Ira Weiny Signed-off-by: Greg Kroah-Hartman --- Documentation/filesystems/sysfs.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt index d78ed0bb275..5d1335faec2 100644 --- a/Documentation/filesystems/sysfs.txt +++ b/Documentation/filesystems/sysfs.txt @@ -4,7 +4,7 @@ sysfs - _The_ filesystem for exporting kernel objects. Patrick Mochel Mike Murphy -Revised: 10 July 2010 +Revised: 15 July 2010 Original: 10 January 2003 @@ -333,7 +333,7 @@ Structure: struct bus_attribute { struct attribute attr; ssize_t (*show)(struct bus_type *, char * buf); - ssize_t (*store)(struct bus_type *, const char * buf); + ssize_t (*store)(struct bus_type *, const char * buf, size_t count); }; Declaring: -- cgit v1.2.3 From c462e8cd57869a81223c5cad2d5a61b491634229 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 20 Jul 2010 16:04:51 -0700 Subject: debugfs: no longer needs to depend on SYSFS debugfs no longer uses 'kernel_subsys' (which is gone), and other kernel/ksysfs.c code is always built, so DEBUG_FS does not need to depend on SYSFS. Fixes this kconfig warning: warning: (TREE_RCU_TRACE || AMD_IOMMU_STATS && AMD_IOMMU || MTD_UBI_DEBUG && MTD && SYSFS && MTD_UBI || UBIFS_FS_DEBUG && MISC_FILESYSTEMS && UBIFS_FS || DEBUG_KMEMLEAK && DEBUG_KERNEL && EXPERIMENTAL && !MEMORY_HOTPLUG && (X86 || ARM || PPC || S390 || SPARC64 || SUPERH || MICROBLAZE) && SYSFS || TRACING || X86_PTDUMP && DEBUG_KERNEL || BLK_DEV_IO_TRACE && TRACING_SUPPORT && FTRACE && SYSFS && BLOCK) selects DEBUG_FS which has unmet direct dependencies (SYSFS) Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- lib/Kconfig.debug | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 154ff43aaa8..4608952884d 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -76,7 +76,6 @@ config UNUSED_SYMBOLS config DEBUG_FS bool "Debug Filesystem" - depends on SYSFS help debugfs is a virtual file system that kernel developers use to put debugging files into. Enable this option to be able to read and -- cgit v1.2.3 From 600c20f34f645adf7884277302b10601583aa7d5 Mon Sep 17 00:00:00 2001 From: Jike Song Date: Thu, 15 Jul 2010 17:43:54 +0800 Subject: driver core: fix memory leak on one error path in bus_register() Reported-by: huangweibing@gmail.com Signed-off-by: Jike Song Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 12eec3f633b..eb1b7fa20dc 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -945,8 +945,8 @@ bus_devices_fail: bus_remove_file(bus, &bus_attr_uevent); bus_uevent_fail: kset_unregister(&bus->p->subsys); - kfree(bus->p); out: + kfree(bus->p); bus->p = NULL; return retval; } -- cgit v1.2.3 From 45daef0fdcc44f6af86fdebc4fc7eb7c79375398 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 23 Jul 2010 19:56:18 +0900 Subject: Driver core: Add BUS_NOTIFY_BIND_DRIVER Add BUS_NOTIFY_BIND_DRIVER as a bus notifier event. For driver binding/unbinding we with this in place have the following bus notifier events: - BUS_NOTIFY_BIND_DRIVER - before ->probe() - BUS_NOTIFY_BOUND_DRIVER - after ->probe() - BUS_NOTIFY_UNBIND_DRIVER - before ->remove() - BUS_NOTIFY_UNBOUND_DRIVER - after ->remove() The event BUS_NOTIFY_BIND_DRIVER allows bus code to be notified that ->probe() is about to be called. Useful for bus code that needs to setup hardware before the driver gets to run. With this in place platform drivers can be loaded and unloaded as modules and the new BIND event allows bus code to control for instance device clocks that must be enabled before the driver can be executed. Without this patch there is no way for the bus code to get notified that a modular driver is about to be probed. Signed-off-by: Magnus Damm Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 4 ++++ include/linux/device.h | 8 +++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 503c2620bbc..da57ee9d63f 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -51,6 +51,10 @@ static int driver_sysfs_add(struct device *dev) { int ret; + if (dev->bus) + blocking_notifier_call_chain(&dev->bus->p->bus_notifier, + BUS_NOTIFY_BIND_DRIVER, dev); + ret = sysfs_create_link(&dev->driver->p->kobj, &dev->kobj, kobject_name(&dev->kobj)); if (ret == 0) { diff --git a/include/linux/device.h b/include/linux/device.h index ddffdf7da39..0ca24e93304 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -109,10 +109,12 @@ extern int bus_unregister_notifier(struct bus_type *bus, */ #define BUS_NOTIFY_ADD_DEVICE 0x00000001 /* device added */ #define BUS_NOTIFY_DEL_DEVICE 0x00000002 /* device removed */ -#define BUS_NOTIFY_BOUND_DRIVER 0x00000003 /* driver bound to device */ -#define BUS_NOTIFY_UNBIND_DRIVER 0x00000004 /* driver about to be +#define BUS_NOTIFY_BIND_DRIVER 0x00000003 /* driver about to be + bound */ +#define BUS_NOTIFY_BOUND_DRIVER 0x00000004 /* driver bound to device */ +#define BUS_NOTIFY_UNBIND_DRIVER 0x00000005 /* driver about to be unbound */ -#define BUS_NOTIFY_UNBOUND_DRIVER 0x00000005 /* driver is unbound +#define BUS_NOTIFY_UNBOUND_DRIVER 0x00000006 /* driver is unbound from the device */ extern struct kset *bus_get_kset(struct bus_type *bus); -- cgit v1.2.3 From 676db4af043014e852f67ba0349dae0071bd11f3 Mon Sep 17 00:00:00 2001 From: Greg KH Date: Thu, 5 Aug 2010 13:53:35 -0700 Subject: cgroupfs: create /sys/fs/cgroup to mount cgroupfs on We really shouldn't be asking userspace to create new root filesystems. So follow along with all of the other in-kernel filesystems, and provide a mount point in sysfs. For cgroupfs, this should be in /sys/fs/cgroup/ This change provides that mount point when the cgroup filesystem is registered in the kernel. Acked-by: Paul Menage Acked-by: Dhaval Giani Cc: Li Zefan Cc: Lennart Poettering Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- kernel/cgroup.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index a8ce0995440..d83cab06da8 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -1623,6 +1623,8 @@ static struct file_system_type cgroup_fs_type = { .kill_sb = cgroup_kill_sb, }; +static struct kobject *cgroup_kobj; + static inline struct cgroup *__d_cgrp(struct dentry *dentry) { return dentry->d_fsdata; @@ -3894,9 +3896,18 @@ int __init cgroup_init(void) hhead = css_set_hash(init_css_set.subsys); hlist_add_head(&init_css_set.hlist, hhead); BUG_ON(!init_root_id(&rootnode)); + + cgroup_kobj = kobject_create_and_add("cgroup", fs_kobj); + if (!cgroup_kobj) { + err = -ENOMEM; + goto out; + } + err = register_filesystem(&cgroup_fs_type); - if (err < 0) + if (err < 0) { + kobject_put(cgroup_kobj); goto out; + } proc_create("cgroups", 0, NULL, &proc_cgroupstats_operations); -- cgit v1.2.3 From 3577dc76fc92c45ff61f8fa85b90e872755796d1 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Wed, 28 Jul 2010 22:09:21 -0700 Subject: scsi: Remove owner field from attribute initialization in LPFC driver Signed-off-by: Guenter Roeck Acked-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/lpfc/lpfc_attr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 868874c28f9..162704cf6a9 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -2778,7 +2778,6 @@ static struct bin_attribute sysfs_drvr_stat_data_attr = { .attr = { .name = "lpfc_drvr_stat_data", .mode = S_IRUSR, - .owner = THIS_MODULE, }, .size = LPFC_MAX_TARGET * MAX_STAT_DATA_SIZE_PER_TARGET, .read = sysfs_drvr_stat_data_read, -- cgit v1.2.3 From cf9e82a8a03cee3c4ffe0a23ca0f17bd57b3cc60 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Wed, 28 Jul 2010 22:09:22 -0700 Subject: scsi: Remove owner field from attribute initialization in ARCMSR driver Signed-off-by: Guenter Roeck Acked-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/arcmsr/arcmsr_attr.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c index 07fdfe57e38..a4e04c50c43 100644 --- a/drivers/scsi/arcmsr/arcmsr_attr.c +++ b/drivers/scsi/arcmsr/arcmsr_attr.c @@ -192,7 +192,6 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = { .attr = { .name = "mu_read", .mode = S_IRUSR , - .owner = THIS_MODULE, }, .size = 1032, .read = arcmsr_sysfs_iop_message_read, @@ -202,7 +201,6 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = { .attr = { .name = "mu_write", .mode = S_IWUSR, - .owner = THIS_MODULE, }, .size = 1032, .write = arcmsr_sysfs_iop_message_write, @@ -212,7 +210,6 @@ static struct bin_attribute arcmsr_sysfs_message_clear_attr = { .attr = { .name = "mu_clear", .mode = S_IWUSR, - .owner = THIS_MODULE, }, .size = 1, .write = arcmsr_sysfs_iop_message_clear, -- cgit v1.2.3 From 0c8617d3abf6a83b05f80179f8729a002f4160ad Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Wed, 28 Jul 2010 22:09:23 -0700 Subject: leds: Remove owner field from attribute initialization in bd2802 driver Signed-off-by: Guenter Roeck Acked-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- drivers/leds/leds-bd2802.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c index 5dcdf9d69b3..19dc4b61a10 100644 --- a/drivers/leds/leds-bd2802.c +++ b/drivers/leds/leds-bd2802.c @@ -351,7 +351,7 @@ static ssize_t bd2802_store_reg##reg_addr(struct device *dev, \ return count; \ } \ static struct device_attribute bd2802_reg##reg_addr##_attr = { \ - .attr = {.name = reg_name, .mode = 0644, .owner = THIS_MODULE}, \ + .attr = {.name = reg_name, .mode = 0644}, \ .store = bd2802_store_reg##reg_addr, \ }; @@ -482,7 +482,6 @@ static struct device_attribute bd2802_adv_conf_attr = { .attr = { .name = "advanced_configuration", .mode = 0644, - .owner = THIS_MODULE }, .show = bd2802_show_adv_conf, .store = bd2802_store_adv_conf, @@ -519,7 +518,6 @@ static struct device_attribute bd2802_##attr_name##_attr = { \ .attr = { \ .name = name_str, \ .mode = 0644, \ - .owner = THIS_MODULE \ }, \ .show = bd2802_show_##attr_name, \ .store = bd2802_store_##attr_name, \ -- cgit v1.2.3 From 068a2782f59efe5855091860bbccbadf1c72fffd Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Wed, 28 Jul 2010 22:09:24 -0700 Subject: regulator: Remove owner field from attribute initialization in regulator core driver Signed-off-by: Guenter Roeck Acked-by: Mark Brown Acked-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- drivers/regulator/core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 2248087b9be..422a709d271 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1025,7 +1025,6 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, if (regulator->dev_attr.attr.name == NULL) goto attr_name_err; - regulator->dev_attr.attr.owner = THIS_MODULE; regulator->dev_attr.attr.mode = 0444; regulator->dev_attr.show = device_requested_uA_show; err = device_create_file(dev, ®ulator->dev_attr); -- cgit v1.2.3 From c4945b0d8ce682eb58b82138aaf4ca2e32b0b757 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Wed, 28 Jul 2010 22:09:25 -0700 Subject: powerpc/pci: Remove owner field from attribute initialization in PCI bridge init Signed-off-by: Guenter Roeck Acked-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/sysdev/mv64x60_pci.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/powerpc/sysdev/mv64x60_pci.c b/arch/powerpc/sysdev/mv64x60_pci.c index 198f288570c..77bb3f4d530 100644 --- a/arch/powerpc/sysdev/mv64x60_pci.c +++ b/arch/powerpc/sysdev/mv64x60_pci.c @@ -73,7 +73,6 @@ static struct bin_attribute mv64x60_hs_reg_attr = { /* Hotswap register */ .attr = { .name = "hs_reg", .mode = S_IRUGO | S_IWUSR, - .owner = THIS_MODULE, }, .size = MV64X60_VAL_LEN_MAX, .read = mv64x60_hs_reg_read, -- cgit v1.2.3 From 6fd69dc578fa0b1bbc3aad70ae3af9a137211707 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Wed, 28 Jul 2010 22:09:26 -0700 Subject: sysfs: Remove owner field from sysfs struct attribute Signed-off-by: Guenter Roeck Acked-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- include/linux/sysfs.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 8bf06b64487..3c92121ba9a 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -22,14 +22,8 @@ struct kobject; struct module; enum kobj_ns_type; -/* FIXME - * The *owner field is no longer used. - * x86 tree has been cleaned up. The owner - * attribute is still left for other arches. - */ struct attribute { const char *name; - struct module *owner; mode_t mode; #ifdef CONFIG_DEBUG_LOCK_ALLOC struct lock_class_key *key; -- cgit v1.2.3 From 6937e8f8c0135f2325194c372ada6dc655499992 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 5 Aug 2010 17:38:18 +0200 Subject: driver core: device_rename's new_name can be const The new_name argument to device_rename() can be const as kobject_rename's new_name argument is. Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 2 +- include/linux/device.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index f8e72724dd4..d1b2c9adc27 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1599,7 +1599,7 @@ EXPORT_SYMBOL_GPL(device_destroy); * on the same device to ensure that new_name is valid and * won't conflict with other devices. */ -int device_rename(struct device *dev, char *new_name) +int device_rename(struct device *dev, const char *new_name) { char *old_class_name = NULL; char *new_class_name = NULL; diff --git a/include/linux/device.h b/include/linux/device.h index 0ca24e93304..516fecacf27 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -552,7 +552,7 @@ extern int device_for_each_child(struct device *dev, void *data, int (*fn)(struct device *dev, void *data)); extern struct device *device_find_child(struct device *dev, void *data, int (*match)(struct device *dev, void *data)); -extern int device_rename(struct device *dev, char *new_name); +extern int device_rename(struct device *dev, const char *new_name); extern int device_move(struct device *dev, struct device *new_parent, enum dpm_order dpm_order); extern const char *device_get_devnode(struct device *dev, -- cgit v1.2.3