From 967857dfd990081f6702daebc6c9bc6f4ba7a39e Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 23 Oct 2012 13:01:50 -0700 Subject: drivers/base: remove CONFIG_EXPERIMENTAL This config item has not carried much meaning for a while now and is almost always enabled by default. As agreed during the Linux kernel summit, remove it. CC: Greg Kroah-Hartman Signed-off-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- drivers/base/Kconfig | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 08b4c52..e439ebc 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -57,7 +57,7 @@ config DEVTMPFS_MOUNT on the rootfs is completely empty. config STANDALONE - bool "Select only drivers that don't need compile-time external firmware" if EXPERIMENTAL + bool "Select only drivers that don't need compile-time external firmware" default y help Select this option if you don't have magic firmware for drivers that @@ -185,7 +185,6 @@ config DMA_SHARED_BUFFER bool default n select ANON_INODES - depends on EXPERIMENTAL help This option enables the framework for buffer-sharing between multiple drivers. A buffer is associated with a file using driver @@ -193,8 +192,8 @@ config DMA_SHARED_BUFFER driver. config CMA - bool "Contiguous Memory Allocator (EXPERIMENTAL)" - depends on HAVE_DMA_CONTIGUOUS && HAVE_MEMBLOCK && EXPERIMENTAL + bool "Contiguous Memory Allocator" + depends on HAVE_DMA_CONTIGUOUS && HAVE_MEMBLOCK select MIGRATION select MEMORY_ISOLATION help -- cgit v1.1 From b1d6d822550ee4e71ab9d55e65f8e096fb11e62b Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 29 Oct 2012 18:04:53 +0100 Subject: drivers/base: fix typo in comment for arch_setup_pdev_archdata() Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 8727e9c..af1d47f 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -44,7 +44,7 @@ EXPORT_SYMBOL_GPL(platform_bus); * be setup before the platform_notifier is called. So if a user needs to * manipulate any relevant information in the pdev_archdata they can do: * - * platform_devic_alloc() + * platform_device_alloc() * ... manipulate ... * platform_device_add() * -- cgit v1.1 From a369a7ebbfce5caa38e3d5645ea050f4590dea7a Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 28 Oct 2012 01:05:41 -0700 Subject: drivers: base: Convert dev_printk(KERN_ to dev_( dev_ calls take less code than dev_printk(KERN_ and reducing object size is good. Signed-off-by: Joe Perches Signed-off-by: Greg Kroah-Hartman --- drivers/base/attribute_container.c | 2 +- drivers/base/devres.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c index 8fc200b..d78b204 100644 --- a/drivers/base/attribute_container.c +++ b/drivers/base/attribute_container.c @@ -158,7 +158,7 @@ attribute_container_add_device(struct device *dev, ic = kzalloc(sizeof(*ic), GFP_KERNEL); if (!ic) { - dev_printk(KERN_ERR, dev, "failed to allocate class container\n"); + dev_err(dev, "failed to allocate class container\n"); continue; } diff --git a/drivers/base/devres.c b/drivers/base/devres.c index 8731979..6683906 100644 --- a/drivers/base/devres.c +++ b/drivers/base/devres.c @@ -50,8 +50,8 @@ static void devres_log(struct device *dev, struct devres_node *node, const char *op) { if (unlikely(log_devres)) - dev_printk(KERN_ERR, dev, "DEVRES %3s %p %s (%lu bytes)\n", - op, node, node->name, (unsigned long)node->size); + dev_err(dev, "DEVRES %3s %p %s (%lu bytes)\n", + op, node, node->name, (unsigned long)node->size); } #else /* CONFIG_DEBUG_DEVRES */ #define set_node_dbginfo(node, n, s) do {} while (0) -- cgit v1.1 From ce2fcbd99cef580623116bb33531dbc3e6f690b0 Mon Sep 17 00:00:00 2001 From: Chuansheng Liu Date: Thu, 8 Nov 2012 19:14:40 +0800 Subject: firmware loader: Fix the race FW_STATUS_DONE is followed by class_timeout There is a race as below when calling request_firmware(): CPU1 CPU2 write 0 > loading mutex_lock(&fw_lock) ... set_bit FW_STATUS_DONE class_timeout is coming set_bit FW_STATUS_ABORT complete_all &completion ... mutex_unlock(&fw_lock) In this time, the bit FW_STATUS_DONE and FW_STATUS_ABORT are set, and request_firmware() will return failure due to condition in _request_firmware_load(): if (!buf->size || test_bit(FW_STATUS_ABORT, &buf->status)) retval = -ENOENT; But from the above scenerio, it should be a successful requesting. So we need judge if the bit FW_STATUS_DONE is already set before calling fw_load_abort() in timeout function. As Ming's proposal, we need change the timer into sched_work to benefit from using &fw_lock mutex also. Signed-off-by: liu chuansheng Acked-by: Ming Lei Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 8945f4e..b44ed35 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -143,7 +143,7 @@ struct fw_cache_entry { }; struct firmware_priv { - struct timer_list timeout; + struct delayed_work timeout_work; bool nowait; struct device dev; struct firmware_buf *buf; @@ -667,11 +667,18 @@ static struct bin_attribute firmware_attr_data = { .write = firmware_data_write, }; -static void firmware_class_timeout(u_long data) +static void firmware_class_timeout_work(struct work_struct *work) { - struct firmware_priv *fw_priv = (struct firmware_priv *) data; + struct firmware_priv *fw_priv = container_of(work, + struct firmware_priv, timeout_work.work); + mutex_lock(&fw_lock); + if (test_bit(FW_STATUS_DONE, &(fw_priv->buf->status))) { + mutex_unlock(&fw_lock); + return; + } fw_load_abort(fw_priv); + mutex_unlock(&fw_lock); } static struct firmware_priv * @@ -690,8 +697,8 @@ fw_create_instance(struct firmware *firmware, const char *fw_name, fw_priv->nowait = nowait; fw_priv->fw = firmware; - setup_timer(&fw_priv->timeout, - firmware_class_timeout, (u_long) fw_priv); + INIT_DELAYED_WORK(&fw_priv->timeout_work, + firmware_class_timeout_work); f_dev = &fw_priv->dev; @@ -858,7 +865,9 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, dev_dbg(f_dev->parent, "firmware: direct-loading" " firmware %s\n", buf->fw_id); + mutex_lock(&fw_lock); set_bit(FW_STATUS_DONE, &buf->status); + mutex_unlock(&fw_lock); complete_all(&buf->completion); direct_load = 1; goto handle_fw; @@ -894,15 +903,14 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, dev_set_uevent_suppress(f_dev, false); dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id); if (timeout != MAX_SCHEDULE_TIMEOUT) - mod_timer(&fw_priv->timeout, - round_jiffies_up(jiffies + timeout)); + schedule_delayed_work(&fw_priv->timeout_work, timeout); kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD); } wait_for_completion(&buf->completion); - del_timer_sync(&fw_priv->timeout); + cancel_delayed_work_sync(&fw_priv->timeout_work); handle_fw: mutex_lock(&fw_lock); -- cgit v1.1 From bd9eb7fbe69111ea0ff1f999ef4a5f26d223d1d5 Mon Sep 17 00:00:00 2001 From: Chuansheng Liu Date: Sat, 10 Nov 2012 01:27:22 +0800 Subject: firmware loader: Fix the concurrent request_firmware() race for kref_get/put There is one race that both request_firmware() with the same firmware name. The race scenerio is as below: CPU1 CPU2 request_firmware() --> _request_firmware_load() return err another request_firmware() is coming --> _request_firmware_cleanup is called --> _request_firmware_prepare --> release_firmware ---> fw_lookup_and_allocate_buf --> spin_lock(&fwc->lock) ... __fw_lookup_buf() return true fw_free_buf() will be called --> ... kref_put --> decrease the refcount to 0 kref_get(&tmp->ref) ==> it will trigger warning due to refcount == 0 __fw_free_buf() --> ... spin_unlock(&fwc->lock) spin_lock(&fwc->lock) list_del(&buf->list) spin_unlock(&fwc->lock) kfree(buf) After that, the freed buf will be used. The key race is decreasing refcount to 0 and list_del is not protected together by fwc->lock, and it is possible another thread try to get it between refcount==0 and list_del. Fix it here to protect it together. Acked-by: Ming Lei Signed-off-by: liu chuansheng Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index b44ed35..be5f7aa 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -246,7 +246,6 @@ static void __fw_free_buf(struct kref *ref) __func__, buf->fw_id, buf, buf->data, (unsigned int)buf->size); - spin_lock(&fwc->lock); list_del(&buf->list); spin_unlock(&fwc->lock); @@ -263,7 +262,10 @@ static void __fw_free_buf(struct kref *ref) static void fw_free_buf(struct firmware_buf *buf) { - kref_put(&buf->ref, __fw_free_buf); + struct firmware_cache *fwc = buf->fwc; + spin_lock(&fwc->lock); + if (!kref_put(&buf->ref, __fw_free_buf)) + spin_unlock(&fwc->lock); } /* direct firmware loading support */ -- cgit v1.1 From 60dac5e284fe99751e3beefe1a9cc7a0771ad73c Mon Sep 17 00:00:00 2001 From: Cesar Eduardo Barros Date: Sat, 27 Oct 2012 20:37:10 -0200 Subject: firmware: use noinline_for_stack The comment above fw_file_size() suggests it is noinline for stack size reasons. Use noinline_for_stack to make this more clear. Signed-off-by: Cesar Eduardo Barros Acked-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index be5f7aa..4b04ec4 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -277,7 +277,7 @@ static const char *fw_path[] = { }; /* Don't inline this: 'struct kstat' is biggish */ -static noinline long fw_file_size(struct file *file) +static noinline_for_stack long fw_file_size(struct file *file) { struct kstat st; if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st)) -- cgit v1.1 From 27602842060484b564cd725241b402b0bddfb830 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sat, 3 Nov 2012 17:47:58 +0800 Subject: firmware loader: introduce module parameter to customize(v4) fw search path This patch introduces one module parameter of 'path' in firmware_class to support customizing firmware image search path, so that people can use its own firmware path if the default built-in paths can't meet their demand[1], and the typical usage is passing the below from kernel command parameter when 'firmware_class' is built in kernel: firmware_class.path=$CUSTOMIZED_PATH [1], https://lkml.org/lkml/2012/10/11/337 Cc: Linus Torvalds Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 4b04ec4..7888af7 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -269,13 +269,23 @@ static void fw_free_buf(struct firmware_buf *buf) } /* direct firmware loading support */ -static const char *fw_path[] = { +static char fw_path_para[256]; +static const char * const fw_path[] = { + fw_path_para, "/lib/firmware/updates/" UTS_RELEASE, "/lib/firmware/updates", "/lib/firmware/" UTS_RELEASE, "/lib/firmware" }; +/* + * Typical usage is that passing 'firmware_class.path=$CUSTOMIZED_PATH' + * from kernel command line because firmware_class is generally built in + * kernel instead of module. + */ +module_param_string(path, fw_path_para, sizeof(fw_path_para), 0644); +MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path"); + /* Don't inline this: 'struct kstat' is biggish */ static noinline_for_stack long fw_file_size(struct file *file) { @@ -317,6 +327,11 @@ static bool fw_get_filesystem_firmware(struct firmware_buf *buf) for (i = 0; i < ARRAY_SIZE(fw_path); i++) { struct file *file; + + /* skip the unset customized path */ + if (!fw_path[i][0]) + continue; + snprintf(path, PATH_MAX, "%s/%s", fw_path[i], buf->fw_id); file = filp_open(path, O_RDONLY, 0); -- cgit v1.1 From 6a927857d890658789e6e54b058ef8527de8200a Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sat, 3 Nov 2012 17:48:16 +0800 Subject: firmware loader: document firmware cache mechanism This patch documents the firmware cache mechanism so that users of request_firmware() know that it can be called safely inside device's suspend and resume callback, and the device's firmware needn't be cached any more by individual driver itself to deal with firmware loss during system resume. Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/base') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 7888af7..d814603 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -988,6 +988,9 @@ err_put_dev: * firmware image for this or any other device. * * Caller must hold the reference count of @device. + * + * The function can be called safely inside device's suspend and + * resume callback. **/ int request_firmware(const struct firmware **firmware_p, const char *name, -- cgit v1.1 From d6ff85513d523551177b1564b62d64c864b97d68 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 13 Nov 2012 17:47:13 +0100 Subject: driver: platform: fix documentation for platform_get_irq_byname Probably due to copy&paste, some stuff was simply forgotten. Signed-off-by: Wolfram Sang Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 1e8f654..d5e3b45 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -122,7 +122,7 @@ struct resource *platform_get_resource_byname(struct platform_device *dev, EXPORT_SYMBOL_GPL(platform_get_resource_byname); /** - * platform_get_irq - get an IRQ for a device + * platform_get_irq_byname - get an IRQ for a device by name * @dev: platform device * @name: IRQ name */ -- cgit v1.1 From 0246c4fafccd6c3580bb33e8d30a2c7927e09f02 Mon Sep 17 00:00:00 2001 From: ShuoX Liu Date: Fri, 23 Nov 2012 15:14:12 +0800 Subject: driver core: use initcall_debug to control shutdown info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit syscore_shutdown uses initcall_debug to control the debug info output. It’s a good programming. But device_shutdown doesn’t. The patch changes device_shutdown to follow the style. Signed-off-by: Yanmin Zhang Signed-off-by: ShuoX Liu Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/core.c b/drivers/base/core.c index abea76c..985f69c 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1840,10 +1840,12 @@ void device_shutdown(void) pm_runtime_barrier(dev); if (dev->bus && dev->bus->shutdown) { - dev_dbg(dev, "shutdown\n"); + if (initcall_debug) + dev_info(dev, "shutdown\n"); dev->bus->shutdown(dev); } else if (dev->driver && dev->driver->shutdown) { - dev_dbg(dev, "shutdown\n"); + if (initcall_debug) + dev_info(dev, "shutdown\n"); dev->driver->shutdown(dev); } -- cgit v1.1 From 93058424af5c555f28175d41384d799f34b4f07e Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 18 Nov 2012 21:27:55 -0800 Subject: drivers/base/core.c: Mark to_root_device static Nothing outside of drivers/base/core.c references this function. Signed-off-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/core.c b/drivers/base/core.c index 985f69c..442e5d3 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1399,7 +1399,7 @@ struct root_device { struct module *owner; }; -inline struct root_device *to_root_device(struct device *d) +static inline struct root_device *to_root_device(struct device *d) { return container_of(d, struct root_device, dev); } -- cgit v1.1 From a42d1e31d4a2380cf1bda8e3510ff1859ddf55a5 Mon Sep 17 00:00:00 2001 From: Bill Pemberton Date: Mon, 19 Nov 2012 13:19:18 -0500 Subject: driver core: remove CONFIG_HOTPLUG ifdefs Remove conditional code based on CONFIG_HOTPLUG being false. It's always on now in preparation of it going away as an option. Signed-off-by: Bill Pemberton Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 181ed26..24eb078 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -164,8 +164,6 @@ static const struct kset_uevent_ops bus_uevent_ops = { static struct kset *bus_kset; - -#ifdef CONFIG_HOTPLUG /* Manually detach a device from its associated driver. */ static ssize_t driver_unbind(struct device_driver *drv, const char *buf, size_t count) @@ -252,7 +250,6 @@ static ssize_t store_drivers_probe(struct bus_type *bus, return -EINVAL; return count; } -#endif static struct device *next_device(struct klist_iter *i) { @@ -618,11 +615,6 @@ static void driver_remove_attrs(struct bus_type *bus, } } -#ifdef CONFIG_HOTPLUG -/* - * Thanks to drivers making their tables __devinit, we can't allow manual - * bind and unbind from userspace unless CONFIG_HOTPLUG is enabled. - */ static int __must_check add_bind_files(struct device_driver *drv) { int ret; @@ -666,12 +658,6 @@ static void remove_probe_files(struct bus_type *bus) bus_remove_file(bus, &bus_attr_drivers_autoprobe); bus_remove_file(bus, &bus_attr_drivers_probe); } -#else -static inline int add_bind_files(struct device_driver *drv) { return 0; } -static inline void remove_bind_files(struct device_driver *drv) {} -static inline int add_probe_files(struct bus_type *bus) { return 0; } -static inline void remove_probe_files(struct bus_type *bus) {} -#endif static ssize_t driver_uevent_store(struct device_driver *drv, const char *buf, size_t count) -- cgit v1.1