From fee0c54e28f6ca187add93dfca226a8093cfa931 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 20 Dec 2013 16:43:50 -0800 Subject: dma-buf: avoid using IS_ERR_OR_NULL dma_buf_map_attachment and dma_buf_vmap can return NULL or ERR_PTR on a error. This encourages a common buggy pattern in callers: sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); if (IS_ERR_OR_NULL(sgt)) return PTR_ERR(sgt); This causes the caller to return 0 on an error. IS_ERR_OR_NULL is almost always a sign of poorly-defined error handling. This patch converts dma_buf_map_attachment to always return ERR_PTR, and fixes the callers that incorrectly handled NULL. There are a few more callers that were not checking for NULL at all, which would have dereferenced a NULL pointer later. There are also a few more callers that correctly handled NULL and ERR_PTR differently, I left those alone but they could also be modified to delete the NULL check. This patch also converts dma_buf_vmap to always return NULL. All the callers to dma_buf_vmap only check for NULL, and would have dereferenced an ERR_PTR and panic'd if one was ever returned. This is not consistent with the rest of the dma buf APIs, but matches the expectations of all of the callers. Signed-off-by: Colin Cross Reviewed-by: Rob Clark Signed-off-by: Greg Kroah-Hartman --- drivers/base/dma-buf.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c index 1e16cbd61da2..cfe1d8bc7bb8 100644 --- a/drivers/base/dma-buf.c +++ b/drivers/base/dma-buf.c @@ -251,9 +251,8 @@ EXPORT_SYMBOL_GPL(dma_buf_put); * @dmabuf: [in] buffer to attach device to. * @dev: [in] device to be attached. * - * Returns struct dma_buf_attachment * for this attachment; may return negative - * error codes. - * + * Returns struct dma_buf_attachment * for this attachment; returns ERR_PTR on + * error. */ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, struct device *dev) @@ -319,9 +318,8 @@ EXPORT_SYMBOL_GPL(dma_buf_detach); * @attach: [in] attachment whose scatterlist is to be returned * @direction: [in] direction of DMA transfer * - * Returns sg_table containing the scatterlist to be returned; may return NULL - * or ERR_PTR. - * + * Returns sg_table containing the scatterlist to be returned; returns ERR_PTR + * on error. */ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, enum dma_data_direction direction) @@ -334,6 +332,8 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, return ERR_PTR(-EINVAL); sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction); + if (!sg_table) + sg_table = ERR_PTR(-ENOMEM); return sg_table; } @@ -544,6 +544,8 @@ EXPORT_SYMBOL_GPL(dma_buf_mmap); * These calls are optional in drivers. The intended use for them * is for mapping objects linear in kernel space for high use objects. * Please attempt to use kmap/kunmap before thinking about these interfaces. + * + * Returns NULL on error. */ void *dma_buf_vmap(struct dma_buf *dmabuf) { @@ -566,7 +568,9 @@ void *dma_buf_vmap(struct dma_buf *dmabuf) BUG_ON(dmabuf->vmap_ptr); ptr = dmabuf->ops->vmap(dmabuf); - if (IS_ERR_OR_NULL(ptr)) + if (WARN_ON_ONCE(IS_ERR(ptr))) + ptr = NULL; + if (!ptr) goto out_unlock; dmabuf->vmap_ptr = ptr; -- cgit v1.2.3 From 6b0afc2a21726b2d6b6aa441af40cafaf5405cc8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 3 Feb 2014 14:03:01 -0500 Subject: kernfs, sysfs, driver-core: implement kernfs_remove_self() and its wrappers Sometimes it's necessary to implement a node which wants to delete nodes including itself. This isn't straightforward because of kernfs active reference. While a file operation is in progress, an active reference is held and kernfs_remove() waits for all such references to drain before completing. For a self-deleting node, this is a deadlock as kernfs_remove() ends up waiting for an active reference that itself is sitting on top of. This currently is worked around in the sysfs layer using sysfs_schedule_callback() which makes such removals asynchronous. While it works, it's rather cumbersome and inherently breaks synchronicity of the operation - the file operation which triggered the operation may complete before the removal is finished (or even started) and the removal may fail asynchronously. If a removal operation is immmediately followed by another operation which expects the specific name to be available (e.g. removal followed by rename onto the same name), there's no way to make the latter operation reliable. The thing is there's no inherent reason for this to be asynchrnous. All that's necessary to do this synchronous is a dedicated operation which drops its own active ref and deactivates self. This patch implements kernfs_remove_self() and its wrappers in sysfs and driver core. kernfs_remove_self() is to be called from one of the file operations, drops the active ref the task is holding, removes the self node, and restores active ref to the dead node so that the ref is balanced afterwards. __kernfs_remove() is updated so that it takes an early exit if the target node is already fully removed so that the active ref restored by kernfs_remove_self() after removal doesn't confuse the deactivation path. This makes implementing self-deleting nodes very easy. The normal removal path doesn't even need to be changed to use kernfs_remove_self() for the self-deleting node. The method can invoke kernfs_remove_self() on itself before proceeding the normal removal path. kernfs_remove() invoked on the node by the normal deletion path will simply be ignored. This will replace sysfs_schedule_callback(). A subtle feature of sysfs_schedule_callback() is that it collapses multiple invocations - even if multiple removals are triggered, the removal callback is run only once. An equivalent effect can be achieved by testing the return value of kernfs_remove_self() - only the one which gets %true return value should proceed with actual deletion. All other instances of kernfs_remove_self() will wait till the enclosing kernfs operation which invoked the winning instance of kernfs_remove_self() finishes and then return %false. This trivially makes all users of kernfs_remove_self() automatically show correct synchronous behavior even when there are multiple concurrent operations - all "echo 1 > delete" instances will finish only after the whole operation is completed by one of the instances. Note that manipulation of active ref is implemented in separate public functions - kernfs_[un]break_active_protection(). kernfs_remove_self() is the only user at the moment but this will be used to cater to more complex cases. v2: For !CONFIG_SYSFS, dummy version kernfs_remove_self() was missing and sysfs_remove_file_self() had incorrect return type. Fix it. Reported by kbuild test bot. v3: kernfs_[un]break_active_protection() separated out from kernfs_remove_self() and exposed as public API. Signed-off-by: Tejun Heo Cc: Alan Stern Cc: kbuild test robot Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers/base') diff --git a/drivers/base/core.c b/drivers/base/core.c index 2b567177ef78..9db57afcf81f 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -570,6 +570,23 @@ void device_remove_file(struct device *dev, } EXPORT_SYMBOL_GPL(device_remove_file); +/** + * device_remove_file_self - remove sysfs attribute file from its own method. + * @dev: device. + * @attr: device attribute descriptor. + * + * See kernfs_remove_self() for details. + */ +bool device_remove_file_self(struct device *dev, + const struct device_attribute *attr) +{ + if (dev) + return sysfs_remove_file_self(&dev->kobj, &attr->attr); + else + return false; +} +EXPORT_SYMBOL_GPL(device_remove_file_self); + /** * device_create_bin_file - create sysfs binary attribute file for device. * @dev: device. -- cgit v1.2.3 From ce8b04aa6c9bdf211b921fdd18c040ea29516b97 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 3 Feb 2014 14:03:05 -0500 Subject: sysfs, driver-core: remove unused {sysfs|device}_schedule_callback_owner() All device_schedule_callback_owner() users are converted to use device_remove_file_self(). Remove now unused {sysfs|device}_schedule_callback_owner(). Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 33 --------------------------------- 1 file changed, 33 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/core.c b/drivers/base/core.c index 9db57afcf81f..4195364f9fdd 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -615,39 +615,6 @@ void device_remove_bin_file(struct device *dev, } EXPORT_SYMBOL_GPL(device_remove_bin_file); -/** - * device_schedule_callback_owner - helper to schedule a callback for a device - * @dev: device. - * @func: callback function to invoke later. - * @owner: module owning the callback routine - * - * Attribute methods must not unregister themselves or their parent device - * (which would amount to the same thing). Attempts to do so will deadlock, - * since unregistration is mutually exclusive with driver callbacks. - * - * Instead methods can call this routine, which will attempt to allocate - * and schedule a workqueue request to call back @func with @dev as its - * argument in the workqueue's process context. @dev will be pinned until - * @func returns. - * - * This routine is usually called via the inline device_schedule_callback(), - * which automatically sets @owner to THIS_MODULE. - * - * Returns 0 if the request was submitted, -ENOMEM if storage could not - * be allocated, -ENODEV if a reference to @owner isn't available. - * - * NOTE: This routine won't work if CONFIG_SYSFS isn't set! It uses an - * underlying sysfs routine (since it is intended for use by attribute - * methods), and if sysfs isn't available you'll get nothing but -ENOSYS. - */ -int device_schedule_callback_owner(struct device *dev, - void (*func)(struct device *), struct module *owner) -{ - return sysfs_schedule_callback(&dev->kobj, - (void (*)(void *)) func, dev, owner); -} -EXPORT_SYMBOL_GPL(device_schedule_callback_owner); - static void klist_children_get(struct klist_node *n) { struct device_private *p = to_device_private_parent(n); -- cgit v1.2.3 From 9383f4c6b66256c039c65ddc141f0caeeae51847 Mon Sep 17 00:00:00 2001 From: Josh Cartwright Date: Thu, 13 Feb 2014 22:00:43 -0600 Subject: ACPI / platform: drop redundant ACPI_HANDLE check The acpi_dev_pm_attach/_detach functions perform their own checks to ensure the device has an ACPI companion. It is not necessary for the caller to do so. This mirrors what other busses with ACPI dev PM support do (i2c, spi, sdio). Cc: Len Brown Acked-by: Rafael J. Wysocki Signed-off-by: Josh Cartwright Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index bc78848dd59a..e714709704e4 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -481,11 +481,10 @@ static int platform_drv_probe(struct device *_dev) struct platform_device *dev = to_platform_device(_dev); int ret; - if (ACPI_HANDLE(_dev)) - acpi_dev_pm_attach(_dev, true); + acpi_dev_pm_attach(_dev, true); ret = drv->probe(dev); - if (ret && ACPI_HANDLE(_dev)) + if (ret) acpi_dev_pm_detach(_dev, true); if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) { @@ -508,8 +507,7 @@ static int platform_drv_remove(struct device *_dev) int ret; ret = drv->remove(dev); - if (ACPI_HANDLE(_dev)) - acpi_dev_pm_detach(_dev, true); + acpi_dev_pm_detach(_dev, true); return ret; } @@ -520,8 +518,7 @@ static void platform_drv_shutdown(struct device *_dev) struct platform_device *dev = to_platform_device(_dev); drv->shutdown(dev); - if (ACPI_HANDLE(_dev)) - acpi_dev_pm_detach(_dev, true); + acpi_dev_pm_detach(_dev, true); } /** -- cgit v1.2.3 From 4272b9611c30f99f51590085998129480f2fe45e Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 21 Jan 2014 16:23:10 -0500 Subject: drivers/base: delete non-required instances of include None of these files are actually using any __init type directives and hence don't need to include . Most are just a left over from __devinit and __cpuinit removal, or simply due to code getting copied from one driver to the next. Cc: Len Brown Signed-off-by: Paul Gortmaker Acked-by: Pavel Machek Acked-by: Rafael J. Wysocki Acked-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/base/attribute_container.c | 1 - drivers/base/power/clock_ops.c | 1 - drivers/base/power/common.c | 1 - drivers/base/power/domain.c | 1 - drivers/base/power/domain_governor.c | 1 - drivers/base/power/opp.c | 1 - drivers/base/regmap/regmap-i2c.c | 1 - drivers/base/regmap/regmap-mmio.c | 1 - drivers/base/regmap/regmap-spi.c | 1 - drivers/base/topology.c | 1 - 10 files changed, 10 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c index ecc1929d7f6a..b84ca8f13f9e 100644 --- a/drivers/base/attribute_container.c +++ b/drivers/base/attribute_container.c @@ -12,7 +12,6 @@ */ #include -#include #include #include #include diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c index e870bbe9ec4e..b99e6c06ee67 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c @@ -6,7 +6,6 @@ * This file is released under the GPLv2. */ -#include #include #include #include diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c index 5da914041305..df2e5eeaeb05 100644 --- a/drivers/base/power/common.c +++ b/drivers/base/power/common.c @@ -6,7 +6,6 @@ * This file is released under the GPLv2. */ -#include #include #include #include diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index bfb8955c406c..921b19234a4d 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -6,7 +6,6 @@ * This file is released under the GPLv2. */ -#include #include #include #include diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c index 28dee3053f1f..a089e3bcdfbc 100644 --- a/drivers/base/power/domain_governor.c +++ b/drivers/base/power/domain_governor.c @@ -6,7 +6,6 @@ * This file is released under the GPLv2. */ -#include #include #include #include diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c index fa4187418440..25538675d59e 100644 --- a/drivers/base/power/opp.c +++ b/drivers/base/power/opp.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c index fa6bf5279d28..ebd189529760 100644 --- a/drivers/base/regmap/regmap-i2c.c +++ b/drivers/base/regmap/regmap-i2c.c @@ -13,7 +13,6 @@ #include #include #include -#include static int regmap_i2c_write(void *context, const void *data, size_t count) { diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c index 81f977510775..4410cb2d7d82 100644 --- a/drivers/base/regmap/regmap-mmio.c +++ b/drivers/base/regmap/regmap-mmio.c @@ -18,7 +18,6 @@ #include #include -#include #include #include #include diff --git a/drivers/base/regmap/regmap-spi.c b/drivers/base/regmap/regmap-spi.c index 37f12ae7aada..0eb3097c0d76 100644 --- a/drivers/base/regmap/regmap-spi.c +++ b/drivers/base/regmap/regmap-spi.c @@ -12,7 +12,6 @@ #include #include -#include #include #include "internal.h" diff --git a/drivers/base/topology.c b/drivers/base/topology.c index 94ffee378f10..ad9d17762664 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c @@ -23,7 +23,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ -#include #include #include #include -- cgit v1.2.3 From 2b1278cb651786648ba6dad285a6c0873c6788e1 Mon Sep 17 00:00:00 2001 From: zhang jun Date: Thu, 13 Feb 2014 15:18:47 +0800 Subject: firmware: give a protection when map page failed so, we need give a protection and return a error value. [ 7341.474236] [drm:do_intel_finish_page_flip] *ERROR* invalid or inactive unpin_work! [ 7341.494464] atomisp-css2400b0_v21 0000:00:03.0: unhandled css stored event: 0x20 [ 7341.503627] vmap allocation for size 208896 failed: use vmalloc= to increase size.<=================== map failed [ 7341.507135] [drm:do_intel_finish_page_flip] *ERROR* invalid or inactive unpin_work! [ 7341.503848] BUG: unable to handle kernel NULL pointer dereference at (null) [ 7341.520394] IP: [] sst_load_all_modules_elf+0x1bb/0x850 [ 7341.527216] *pdpt = 0000000030dfe001 *pde = 0000000000000000 [ 7341.533640] Oops: 0000 [#1] PREEMPT SMP [ 7341.540360] [drm:do_intel_finish_page_flip] *ERROR* invalid or inactive unpin_work! [ 7341.538037] Modules linked in: atomisp_css2400b0_v21 lm3554 ov2722 imx1x5 atmel_mxt_ts vxd392 videobuf_vmalloc videobuf_core lm_dump(O) bcm_bt_lpm hdmi_audio bcm4334x(O) [ 7341.563531] CPU: 1 PID: 525 Comm: mediaserver Tainted: G W O 3.10.20-262518-ga83c053 #1 [ 7341.573253] task: f0994ec0 ti: f09f0000 task.ti: f09f0000 [ 7341.579284] EIP: 0060:[] EFLAGS: 00010246 CPU: 1 [ 7341.585415] EIP is at sst_load_all_modules_elf+0x1bb/0x850 [ 7341.591541] EAX: 00000000 EBX: e3595ba0 ECX: 00000000 EDX: 00031c1c [ 7341.598541] ESI: e04a0000 EDI: 00000000 EBP: f09f1d80 ESP: f09f1cf4 [ 7341.605542] DS: 007b ES: 007b FS: 00d8 GS: 003b SS: 0068 [ 7341.611573] CR0: 80050033 CR2: 00000000 CR3: 30db4000 CR4: 001007f0 [ 7341.618573] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [ 7341.625575] DR6: ffff0ff0 DR7: 00000400 [ 7341.629856] Stack: [ 7341.632097] f09f1d57 00000019 c1d656d7 c1d658d3 c1d56409 00000f28 c1d64af9 18000103 [ 7341.640766] 01000001 00080000 c1f910a0 f326f4c8 00000034 f326f520 00000002 e04a02bc [ 7341.649465] 00000001 f326e014 c1f910b0 e04a0000 c0080100 00031c1c e3595ba0 c0080100 [ 7341.658149] Call Trace: [ 7341.660888] [] sst_post_download_byt+0x58/0xb0 [ 7341.666925] [] sst_load_fw+0xdc/0x510 [ 7341.672086] [] ? __mutex_lock_slowpath+0x250/0x370 [ 7341.678507] [] ? sub_preempt_count+0x55/0xe0 [ 7341.684346] [] sst_download_fw+0x14/0x60 [ 7341.689796] [] ? mutex_lock+0x23/0x30 [ 7341.694954] [] intel_sst_check_device+0x6c/0x120 [ 7341.701181] [] sst_set_generic_params+0x1b8/0x4a0 [ 7341.707504] [] ? sub_preempt_count+0x55/0xe0 [ 7341.713341] [] ? sub_preempt_count+0x55/0xe0 [ 7341.719178] [] ? __mutex_lock_slowpath+0x250/0x370 [ 7341.725600] [] ? __kmalloc_track_caller+0xe4/0x1d0 [ 7341.732022] [] sst_set_mixer_param+0x25/0x40 [ 7341.737859] [] lpe_mixer_ihf_set+0xb3/0x160 [ 7341.743602] [] snd_ctl_ioctl+0xa89/0xb40 [ 7341.749052] [] ? path_openat+0xa5/0x3d0 [ 7341.754409] [] ? avc_has_perm_flags+0xc7/0x170 [ 7341.760441] [] ? snd_ctl_elem_add_user+0x540/0x540 [ 7341.766862] [] do_vfs_ioctl+0x77/0x5e0 [ 7341.772117] [] ? inode_has_perm.isra.42.constprop.79+0x3a/0x50 [ 7341.779705] [] ? file_has_perm+0xa0/0xb0 [ 7341.785155] [] ? selinux_file_ioctl+0x48/0xe0 [ 7341.791090] [] SyS_ioctl+0x78/0x90 [ 7341.795958] [] syscall_call+0x7/0xb [ 7341.800925] [] ? mm_fault_error+0x13c/0x198 Signed-off-by: zhang jun Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 8a97ddfa6122..e5808eb63b67 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -649,7 +649,9 @@ static ssize_t firmware_loading_store(struct device *dev, * see the mapped 'buf->data' once the loading * is completed. * */ - fw_map_pages_buf(fw_buf); + if (fw_map_pages_buf(fw_buf)) + dev_err(dev, "%s: map pages failed\n", + __func__); list_del_init(&fw_buf->pending_list); complete_all(&fw_buf->completion); break; @@ -908,6 +910,8 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, wait_for_completion(&buf->completion); cancel_delayed_work_sync(&fw_priv->timeout_work); + if (!buf->data) + retval = -ENOMEM; device_remove_file(f_dev, &dev_attr_loading); err_del_bin_attr: -- cgit v1.2.3 From bce6618a11ca4ca3cb5d6a2a1d43c00f8301d2b2 Mon Sep 17 00:00:00 2001 From: Shaibal Dutta Date: Fri, 31 Jan 2014 15:44:58 -0800 Subject: firmware: use power efficient workqueue for unloading and aborting fw load Allow the scheduler to select the most appropriate CPU for running the firmware load timeout routine and delayed routine for firmware unload. This extends idle residency times and conserves power. This functionality is enabled when CONFIG_WQ_POWER_EFFICIENT is selected. Cc: Ming Lei Cc: Greg Kroah-Hartman Signed-off-by: Shaibal Dutta [zoran.markovic@linaro.org: Rebased to latest kernel, added commit message. Fixed code alignment.] Signed-off-by: Zoran Markovic Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index e5808eb63b67..cb8b77917d7f 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -902,7 +902,8 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, dev_set_uevent_suppress(f_dev, false); dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id); if (timeout != MAX_SCHEDULE_TIMEOUT) - schedule_delayed_work(&fw_priv->timeout_work, timeout); + queue_delayed_work(system_power_efficient_wq, + &fw_priv->timeout_work, timeout); kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD); } @@ -1574,8 +1575,8 @@ static void device_uncache_fw_images_work(struct work_struct *work) */ static void device_uncache_fw_images_delay(unsigned long delay) { - schedule_delayed_work(&fw_cache.work, - msecs_to_jiffies(delay)); + queue_delayed_work(system_power_efficient_wq, &fw_cache.work, + msecs_to_jiffies(delay)); } static int fw_pm_notify(struct notifier_block *notify_block, -- cgit v1.2.3 From 5c764dfaefc582d9c3e2bbd52ae2e30747af8a37 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 8 Feb 2014 09:59:02 +0800 Subject: driver core: unexport static function create_syslog_header Function create_syslog_header() is defined as static, so it should not be exported. Signed-off-by: Jiang Liu Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/core.c b/drivers/base/core.c index 4195364f9fdd..80b6a9b22f3e 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -2042,7 +2042,6 @@ create_syslog_header(const struct device *dev, char *hdr, size_t hdrlen) return pos; } -EXPORT_SYMBOL(create_syslog_header); int dev_vprintk_emit(int level, const struct device *dev, const char *fmt, va_list args) -- cgit v1.2.3 From 67bad2fdb754dbef14596c0b5d28b3a12c8dfe84 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Sat, 8 Feb 2014 13:34:09 +0100 Subject: cpu: add generic support for CPU feature based module autoloading This patch adds support for advertising optional CPU features over udev using the modalias, and for declaring compatibility with/dependency upon such a feature in a module. The mapping between feature numbers and actual features should be provided by the architecture in a file called which exports the following functions/macros: - cpu_feature(FEAT), a preprocessor macro that maps token FEAT to a numeric index; - bool cpu_have_feature(n), returning whether this CPU has support for feature #n; - MAX_CPU_FEATURES, an upper bound for 'n' in the previous function. The feature can then be enabled by setting CONFIG_GENERIC_CPU_AUTOPROBE for the architecture. For instance, a module that registers its module init function using module_cpu_feature_match(FEAT_X, module_init_function) will be probed automatically when the CPU's support for the 'FEAT_X' feature is advertised over udev, and will only allow the module to be loaded by hand if the 'FEAT_X' feature is supported. Signed-off-by: Ard Biesheuvel Signed-off-by: Greg Kroah-Hartman --- drivers/base/Kconfig | 8 ++++++++ drivers/base/cpu.c | 50 +++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 53 insertions(+), 5 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index ec36e7772e57..3f0d3732df7f 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -185,6 +185,14 @@ config GENERIC_CPU_DEVICES bool default n +config HAVE_CPU_AUTOPROBE + def_bool ARCH_HAS_CPU_AUTOPROBE + +config GENERIC_CPU_AUTOPROBE + bool + depends on !ARCH_HAS_CPU_AUTOPROBE + select HAVE_CPU_AUTOPROBE + config SOC_BUS bool diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index f48370dfc908..8a38bf8c792f 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "base.h" @@ -286,6 +287,45 @@ static void cpu_device_release(struct device *dev) */ } +#ifdef CONFIG_HAVE_CPU_AUTOPROBE +#ifdef CONFIG_GENERIC_CPU_AUTOPROBE +static ssize_t print_cpu_modalias(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + ssize_t n; + u32 i; + + n = sprintf(buf, "cpu:type:" CPU_FEATURE_TYPEFMT ":feature:", + CPU_FEATURE_TYPEVAL); + + for (i = 0; i < MAX_CPU_FEATURES; i++) + if (cpu_have_feature(i)) { + if (PAGE_SIZE < n + sizeof(",XXXX\n")) { + WARN(1, "CPU features overflow page\n"); + break; + } + n += sprintf(&buf[n], ",%04X", i); + } + buf[n++] = '\n'; + return n; +} +#else +#define print_cpu_modalias arch_print_cpu_modalias +#endif + +static int cpu_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (buf) { + print_cpu_modalias(NULL, NULL, buf); + add_uevent_var(env, "MODALIAS=%s", buf); + kfree(buf); + } + return 0; +} +#endif + /* * register_cpu - Setup a sysfs device for a CPU. * @cpu - cpu->hotpluggable field set to 1 will generate a control file in @@ -306,8 +346,8 @@ int register_cpu(struct cpu *cpu, int num) cpu->dev.offline_disabled = !cpu->hotpluggable; cpu->dev.offline = !cpu_online(num); cpu->dev.of_node = of_get_cpu_node(num, NULL); -#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE - cpu->dev.bus->uevent = arch_cpu_uevent; +#ifdef CONFIG_HAVE_CPU_AUTOPROBE + cpu->dev.bus->uevent = cpu_uevent; #endif cpu->dev.groups = common_cpu_attr_groups; if (cpu->hotpluggable) @@ -330,8 +370,8 @@ struct device *get_cpu_device(unsigned cpu) } EXPORT_SYMBOL_GPL(get_cpu_device); -#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE -static DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL); +#ifdef CONFIG_HAVE_CPU_AUTOPROBE +static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL); #endif static struct attribute *cpu_root_attrs[] = { @@ -344,7 +384,7 @@ static struct attribute *cpu_root_attrs[] = { &cpu_attrs[2].attr.attr, &dev_attr_kernel_max.attr, &dev_attr_offline.attr, -#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE +#ifdef CONFIG_HAVE_CPU_AUTOPROBE &dev_attr_modalias.attr, #endif NULL -- cgit v1.2.3 From 2b9c1f03278ab7cd421f14ce24dee39091ecb064 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Sat, 8 Feb 2014 13:34:10 +0100 Subject: x86: align x86 arch with generic CPU modalias handling The x86 CPU feature modalias handling existed before it was reimplemented generically. This patch aligns the x86 handling so that it (a) reuses some more code that is now generic; (b) uses the generic format for the modalias module metadata entry, i.e., it now uses 'cpu:type:x86,venVVVVfamFFFFmodMMMM:feature:,XXXX,YYYY' instead of the 'x86cpu:vendor:VVVV:family:FFFF:model:MMMM:feature:,XXXX,YYYY' that was used before. Signed-off-by: Ard Biesheuvel Acked-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman --- drivers/base/Kconfig | 5 ----- drivers/base/cpu.c | 10 +++------- 2 files changed, 3 insertions(+), 12 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 3f0d3732df7f..8fa8deab6449 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -185,13 +185,8 @@ config GENERIC_CPU_DEVICES bool default n -config HAVE_CPU_AUTOPROBE - def_bool ARCH_HAS_CPU_AUTOPROBE - config GENERIC_CPU_AUTOPROBE bool - depends on !ARCH_HAS_CPU_AUTOPROBE - select HAVE_CPU_AUTOPROBE config SOC_BUS bool diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 8a38bf8c792f..006b1bc5297d 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -287,7 +287,6 @@ static void cpu_device_release(struct device *dev) */ } -#ifdef CONFIG_HAVE_CPU_AUTOPROBE #ifdef CONFIG_GENERIC_CPU_AUTOPROBE static ssize_t print_cpu_modalias(struct device *dev, struct device_attribute *attr, @@ -310,9 +309,6 @@ static ssize_t print_cpu_modalias(struct device *dev, buf[n++] = '\n'; return n; } -#else -#define print_cpu_modalias arch_print_cpu_modalias -#endif static int cpu_uevent(struct device *dev, struct kobj_uevent_env *env) { @@ -346,7 +342,7 @@ int register_cpu(struct cpu *cpu, int num) cpu->dev.offline_disabled = !cpu->hotpluggable; cpu->dev.offline = !cpu_online(num); cpu->dev.of_node = of_get_cpu_node(num, NULL); -#ifdef CONFIG_HAVE_CPU_AUTOPROBE +#ifdef CONFIG_GENERIC_CPU_AUTOPROBE cpu->dev.bus->uevent = cpu_uevent; #endif cpu->dev.groups = common_cpu_attr_groups; @@ -370,7 +366,7 @@ struct device *get_cpu_device(unsigned cpu) } EXPORT_SYMBOL_GPL(get_cpu_device); -#ifdef CONFIG_HAVE_CPU_AUTOPROBE +#ifdef CONFIG_GENERIC_CPU_AUTOPROBE static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL); #endif @@ -384,7 +380,7 @@ static struct attribute *cpu_root_attrs[] = { &cpu_attrs[2].attr.attr, &dev_attr_kernel_max.attr, &dev_attr_offline.attr, -#ifdef CONFIG_HAVE_CPU_AUTOPROBE +#ifdef CONFIG_GENERIC_CPU_AUTOPROBE &dev_attr_modalias.attr, #endif NULL -- cgit v1.2.3 From aa0689b36b2144e91d2182605bed951565c4899b Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 4 Mar 2014 19:57:51 -0800 Subject: Revert "driver core: synchronize device shutdown" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 401097ea4b89846d66ac78f7f108d49c2e922d9c. The original changelog said: A patch series to make .shutdown execute asynchronously. Some drivers's shutdown can take a lot of time. The patches can help save some shutdown time. The patches use Arjan's async API. This patch: synchronize all tasks submitted by .shutdown However, I'm not able to find any evidence that any other patches from this series were applied, nor am I able to find any async tasks that are scheduled in a .shutdown context. On the other hand, we see occasional hangs on shutdown that appear to be caused by the async_synchronize_full() in device_shutdown() waiting forever for the async probing in sd if a SCSI disk shows up at just the wrong time — the system starts the probe, but begins shutting down and tears down too much of the SCSI driver to finish the probe. If we had any async shutdown tasks, I guess the right fix would be to create a "shutdown" async domain and have device_shutdown() only wait for that domain. But since there apparently are no async shutdown tasks, we can just revert the waiting. Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/core.c b/drivers/base/core.c index 80b6a9b22f3e..20da3ad1696b 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -1987,7 +1986,6 @@ void device_shutdown(void) spin_lock(&devices_kset->list_lock); } spin_unlock(&devices_kset->list_lock); - async_synchronize_full(); } /* -- cgit v1.2.3 From 92d585ef067da7a966d6ce78c601bd1562b62619 Mon Sep 17 00:00:00 2001 From: Xishi Qiu Date: Thu, 6 Mar 2014 17:18:21 +0800 Subject: numa: fix NULL pointer access and memory leak in unregister_one_node() When doing socket hot remove, "node_devices[nid]" is set to NULL; acpi_processor_remove() try_offline_node() unregister_one_node() Then hot add a socket, but do not echo 1 > /sys/devices/system/cpu/cpuXX/online, so register_one_node() will not be called, and "node_devices[nid]" is still NULL. If doing socket hot remove again, NULL pointer access will be happen. unregister_one_node() unregister_node() Another, we should free the memory used by "node_devices[nid]" in unregister_one_node(). Signed-off-by: Xishi Qiu Signed-off-by: Greg Kroah-Hartman --- drivers/base/node.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/base') diff --git a/drivers/base/node.c b/drivers/base/node.c index bc9f43bf7e29..8f7ed9933a7c 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -599,7 +599,11 @@ int register_one_node(int nid) void unregister_one_node(int nid) { + if (!node_devices[nid]) + return; + unregister_node(node_devices[nid]); + kfree(node_devices[nid]); node_devices[nid] = NULL; } -- cgit v1.2.3 From 72099304eeb316c4b00df3ae83efe4375729bd78 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 25 Mar 2014 20:54:57 -0700 Subject: Revert "sysfs, driver-core: remove unused {sysfs|device}_schedule_callback_owner()" This reverts commit d1ba277e79889085a2faec3b68b91ce89c63f888. As reported by Stephen, this patch breaks linux-next as a ppc patch suddenly (after 2 years) started using this old api call. So revert it for now, it will go away in 3.15-rc2 when we can change the PPC call to the new api. Reported-by: Stephen Rothwell Cc: Tejun Heo Cc: Stewart Smith Cc: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'drivers/base') diff --git a/drivers/base/core.c b/drivers/base/core.c index 20da3ad1696b..0dd65281cc65 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -614,6 +614,39 @@ void device_remove_bin_file(struct device *dev, } EXPORT_SYMBOL_GPL(device_remove_bin_file); +/** + * device_schedule_callback_owner - helper to schedule a callback for a device + * @dev: device. + * @func: callback function to invoke later. + * @owner: module owning the callback routine + * + * Attribute methods must not unregister themselves or their parent device + * (which would amount to the same thing). Attempts to do so will deadlock, + * since unregistration is mutually exclusive with driver callbacks. + * + * Instead methods can call this routine, which will attempt to allocate + * and schedule a workqueue request to call back @func with @dev as its + * argument in the workqueue's process context. @dev will be pinned until + * @func returns. + * + * This routine is usually called via the inline device_schedule_callback(), + * which automatically sets @owner to THIS_MODULE. + * + * Returns 0 if the request was submitted, -ENOMEM if storage could not + * be allocated, -ENODEV if a reference to @owner isn't available. + * + * NOTE: This routine won't work if CONFIG_SYSFS isn't set! It uses an + * underlying sysfs routine (since it is intended for use by attribute + * methods), and if sysfs isn't available you'll get nothing but -ENOSYS. + */ +int device_schedule_callback_owner(struct device *dev, + void (*func)(struct device *), struct module *owner) +{ + return sysfs_schedule_callback(&dev->kobj, + (void (*)(void *)) func, dev, owner); +} +EXPORT_SYMBOL_GPL(device_schedule_callback_owner); + static void klist_children_get(struct klist_node *n) { struct device_private *p = to_device_private_parent(n); -- cgit v1.2.3