From 24ef5f360f22e4408cb49d75755d27d5a21820f7 Mon Sep 17 00:00:00 2001 From: Nicolai Stange Date: Tue, 24 May 2016 13:08:52 +0200 Subject: debugfs: remove extra debugfs_create_file_unsafe() declaration debugfs_create_file_unsafe() is declared twice in exactly the same manner each: once in fs/debugfs/internal.h and once in include/linux/debugfs.h All files that include the former also include the latter and thus, the declaration in fs/debugfs/internal.h is superfluous. Remove it. Signed-off-by: Nicolai Stange Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/internal.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fs/debugfs/internal.h b/fs/debugfs/internal.h index bba52634b995..b3e8443a1f47 100644 --- a/fs/debugfs/internal.h +++ b/fs/debugfs/internal.h @@ -19,8 +19,4 @@ extern const struct file_operations debugfs_noop_file_operations; extern const struct file_operations debugfs_open_proxy_file_operations; extern const struct file_operations debugfs_full_proxy_file_operations; -struct dentry *debugfs_create_file_unsafe(const char *name, umode_t mode, - struct dentry *parent, void *data, - const struct file_operations *fops); - #endif /* _DEBUGFS_INTERNAL_H_ */ -- cgit v1.2.3-59-g8ed1b From cebf8fd16900fdfd58c0028617944f808f97fe50 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sun, 10 Jul 2016 19:27:36 +0800 Subject: driver core: fix race between creating/querying glue dir and its cleanup The global mutex of 'gdp_mutex' is used to serialize creating/querying glue dir and its cleanup. Turns out it isn't a perfect way because part(kobj_kset_leave()) of the actual cleanup action() is done inside the release handler of the glue dir kobject. That means gdp_mutex has to be held before releasing the last reference count of the glue dir kobject. This patch moves glue dir's cleanup after kobject_del() in device_del() for avoiding the race. Cc: Yijing Wang Reported-by: Chandra Sekhar Lingutla Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 0a8bdade53f2..88df65d1e6f6 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -836,11 +836,29 @@ static struct kobject *get_device_parent(struct device *dev, return NULL; } +static inline bool live_in_glue_dir(struct kobject *kobj, + struct device *dev) +{ + if (!kobj || !dev->class || + kobj->kset != &dev->class->p->glue_dirs) + return false; + return true; +} + +static inline struct kobject *get_glue_dir(struct device *dev) +{ + return dev->kobj.parent; +} + +/* + * make sure cleaning up dir as the last step, we need to make + * sure .release handler of kobject is run with holding the + * global lock + */ static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir) { /* see if we live in a "glue" directory */ - if (!glue_dir || !dev->class || - glue_dir->kset != &dev->class->p->glue_dirs) + if (!live_in_glue_dir(glue_dir, dev)) return; mutex_lock(&gdp_mutex); @@ -848,11 +866,6 @@ static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir) mutex_unlock(&gdp_mutex); } -static void cleanup_device_parent(struct device *dev) -{ - cleanup_glue_dir(dev, dev->kobj.parent); -} - static int device_add_class_symlinks(struct device *dev) { struct device_node *of_node = dev_of_node(dev); @@ -1028,6 +1041,7 @@ int device_add(struct device *dev) struct kobject *kobj; struct class_interface *class_intf; int error = -EINVAL; + struct kobject *glue_dir = NULL; dev = get_device(dev); if (!dev) @@ -1072,8 +1086,10 @@ int device_add(struct device *dev) /* first, register with generic layer. */ /* we require the name to be set before, and pass NULL */ error = kobject_add(&dev->kobj, dev->kobj.parent, NULL); - if (error) + if (error) { + glue_dir = get_glue_dir(dev); goto Error; + } /* notify platform of device entry */ if (platform_notify) @@ -1154,9 +1170,10 @@ done: device_remove_file(dev, &dev_attr_uevent); attrError: kobject_uevent(&dev->kobj, KOBJ_REMOVE); + glue_dir = get_glue_dir(dev); kobject_del(&dev->kobj); Error: - cleanup_device_parent(dev); + cleanup_glue_dir(dev, glue_dir); put_device(parent); name_error: kfree(dev->p); @@ -1232,6 +1249,7 @@ EXPORT_SYMBOL_GPL(put_device); void device_del(struct device *dev) { struct device *parent = dev->parent; + struct kobject *glue_dir = NULL; struct class_interface *class_intf; /* Notify clients of device removal. This call must come @@ -1276,8 +1294,9 @@ void device_del(struct device *dev) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_REMOVED_DEVICE, dev); kobject_uevent(&dev->kobj, KOBJ_REMOVE); - cleanup_device_parent(dev); + glue_dir = get_glue_dir(dev); kobject_del(&dev->kobj); + cleanup_glue_dir(dev, glue_dir); put_device(parent); } EXPORT_SYMBOL_GPL(device_del); -- cgit v1.2.3-59-g8ed1b From bea5b158ff0da9c7246ff391f754f5f38e34577a Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 11 Aug 2016 10:20:58 -0500 Subject: driver core: add test of driver remove calls during probe In recent discussions on ksummit-discuss[1], it was suggested to do a sequence of probe, remove, probe for testing driver remove paths. This adds a kconfig option for said test. [1] https://lists.linuxfoundation.org/pipermail/ksummit-discuss/2016-August/003459.html Suggested-by: Arnd Bergmann Cc: Greg Kroah-Hartman Signed-off-by: Rob Herring Signed-off-by: Greg Kroah-Hartman --- drivers/base/Kconfig | 10 ++++++++++ drivers/base/dd.c | 21 +++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 98504ec99c7d..fdf44cac08e6 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -212,6 +212,16 @@ config DEBUG_DEVRES If you are unsure about this, Say N here. +config DEBUG_TEST_DRIVER_REMOVE + bool "Test driver remove calls during probe" + depends on DEBUG_KERNEL + help + Say Y here if you want the Driver core to test driver remove functions + by calling probe, remove, probe. This tests the remove path without + having to unbind the driver or unload the driver module. + + If you are unsure about this, say N here. + config SYS_HYPERVISOR bool default n diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 16688f50729c..4910e6db2a34 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -329,6 +329,7 @@ static int really_probe(struct device *dev, struct device_driver *drv) { int ret = -EPROBE_DEFER; int local_trigger_count = atomic_read(&deferred_trigger_count); + bool test_remove = IS_ENABLED(CONFIG_DEBUG_TEST_DRIVER_REMOVE); if (defer_all_probes) { /* @@ -346,6 +347,7 @@ static int really_probe(struct device *dev, struct device_driver *drv) drv->bus->name, __func__, drv->name, dev_name(dev)); WARN_ON(!list_empty(&dev->devres_head)); +re_probe: dev->driver = drv; /* If using pinctrl, bind pins now before probing */ @@ -383,6 +385,25 @@ static int really_probe(struct device *dev, struct device_driver *drv) goto probe_failed; } + if (test_remove) { + test_remove = false; + + if (dev->bus && dev->bus->remove) + dev->bus->remove(dev); + else if (drv->remove) + drv->remove(dev); + + devres_release_all(dev); + driver_sysfs_remove(dev); + dev->driver = NULL; + dev_set_drvdata(dev, NULL); + if (dev->pm_domain && dev->pm_domain->dismiss) + dev->pm_domain->dismiss(dev); + pm_runtime_reinit(dev); + + goto re_probe; + } + pinctrl_init_done(dev); if (dev->pm_domain && dev->pm_domain->sync) -- cgit v1.2.3-59-g8ed1b From c90aab9c96c2a7f7bf3f7a54167dc5c0ba2b178c Mon Sep 17 00:00:00 2001 From: Jerome Marchand Date: Mon, 25 Jul 2016 16:13:32 +0200 Subject: platform driver: fix use-after-free in platform_device_del() In platform_device_del(), the device is still used after a call to device_del(). At this point there is no guarantee that the device is still there and there could be a use-after-free access. Move the call to device_remove_properties() before device_del() to fix that. Signed-off-by: Jerome Marchand Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 6482d47deb50..f57fff3f268b 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -434,6 +434,7 @@ void platform_device_del(struct platform_device *pdev) int i; if (pdev) { + device_remove_properties(&pdev->dev); device_del(&pdev->dev); if (pdev->id_auto) { @@ -446,8 +447,6 @@ void platform_device_del(struct platform_device *pdev) if (r->parent) release_resource(r); } - - device_remove_properties(&pdev->dev); } } EXPORT_SYMBOL_GPL(platform_device_del); -- cgit v1.2.3-59-g8ed1b From 85714108e673cdebf1b96abfd50fb02a29e37577 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Thu, 21 Jul 2016 16:04:21 +0800 Subject: drivers: base: dma-mapping: page align the size when unmap_kernel_range When dma_common_free_remap, the input parameter 'size' may not be page aligned. And, met kernel warning when doing iommu dma for usb on i.MX8 platform: " WARNING: CPU: 0 PID: 869 at mm/vmalloc.c:70 vunmap_page_range+0x1cc/0x1d0() Modules linked in: CPU: 0 PID: 869 Comm: kworker/u8:2 Not tainted 4.1.12-00444-gc5f9d1d-dirty #147 Hardware name: Freescale i.MX8DV Sabreauto (DT) Workqueue: ci_otg ci_otg_work Call trace: [] dump_backtrace+0x0/0x124 [] show_stack+0x10/0x1c [] dump_stack+0x84/0xc8 [] warn_slowpath_common+0x98/0xd0 [] warn_slowpath_null+0x14/0x20 [] vunmap_page_range+0x1c8/0x1d0 [] unmap_kernel_range+0x20/0x88 [] dma_common_free_remap+0x74/0x84 [] __iommu_free_attrs+0x9c/0x178 [] ehci_mem_cleanup+0x140/0x194 [] ehci_stop+0x8c/0xdc [] usb_remove_hcd+0xf0/0x1cc [] host_stop+0x1c/0x58 [] ci_otg_work+0xdc/0x120 [] process_one_work+0x134/0x33c [] worker_thread+0x13c/0x47c [] kthread+0xd8/0xf0 " For dma_common_pages_remap: dma_common_pages_remap |->get_vm_area_caller |->__get_vm_area_node |->size = PAGE_ALIGN(size); Round up to page aligned So, in dma_common_free_remap, we also need a page aligned size, pass 'PAGE_ALIGN(size)' to unmap_kernel_range. Signed-off-by: Peng Fan Cc: Greg Kroah-Hartman Cc: Signed-off-by: Greg Kroah-Hartman --- drivers/base/dma-mapping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c index d799662f19eb..261420ddfe66 100644 --- a/drivers/base/dma-mapping.c +++ b/drivers/base/dma-mapping.c @@ -334,7 +334,7 @@ void dma_common_free_remap(void *cpu_addr, size_t size, unsigned long vm_flags) return; } - unmap_kernel_range((unsigned long)cpu_addr, size); + unmap_kernel_range((unsigned long)cpu_addr, PAGE_ALIGN(size)); vunmap(cpu_addr); } #endif -- cgit v1.2.3-59-g8ed1b From 426bc8e789f8ac84270b196191904d347586032f Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 3 Jul 2016 14:22:51 -0400 Subject: base: soc: make it explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/base/Kconfig:config SOC_BUS drivers/base/Kconfig: bool ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init was not in use by this code, the init ordering remains unchanged with this commit. Cc: Lee Jones Cc: Greg Kroah-Hartman Signed-off-by: Paul Gortmaker Signed-off-by: Greg Kroah-Hartman --- drivers/base/soc.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/base/soc.c b/drivers/base/soc.c index 75b98aad6faf..b63f23e6ad61 100644 --- a/drivers/base/soc.c +++ b/drivers/base/soc.c @@ -6,7 +6,6 @@ */ #include -#include #include #include #include @@ -160,11 +159,3 @@ static int __init soc_bus_register(void) return bus_register(&soc_bus_type); } core_initcall(soc_bus_register); - -static void __exit soc_bus_unregister(void) -{ - ida_destroy(&soc_ida); - - bus_unregister(&soc_bus_type); -} -module_exit(soc_bus_unregister); -- cgit v1.2.3-59-g8ed1b From 03aca7b260ea2aadf92596d2f57160e4aee8ffb0 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Wed, 1 Jun 2016 09:18:40 +0800 Subject: attribute_container: Fix typo The 't' in "function" was missing, this patch fixes this typo: s/funcion/function/g Signed-off-by: Xiubo Li Signed-off-by: Greg Kroah-Hartman --- drivers/base/attribute_container.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c index 2ba4cac080c5..95e3ef82f3b7 100644 --- a/drivers/base/attribute_container.c +++ b/drivers/base/attribute_container.c @@ -243,7 +243,7 @@ attribute_container_remove_device(struct device *dev, * @dev: The generic device to run the trigger for * @fn the function to execute for each classdev. * - * This funcion is for executing a trigger when you need to know both + * This function is for executing a trigger when you need to know both * the container and the classdev. If you only care about the * container, then use attribute_container_trigger() instead. */ -- cgit v1.2.3-59-g8ed1b From e688f144305c678fb65138d9e6b6ce436e59778b Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Sat, 21 May 2016 18:52:57 +0530 Subject: drivers: dma-coherent: use vma_pages(). Replace explicit computation of vma page count by a call to vma_pages() Signed-off-by: Muhammad Falak R Wani 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 bdf28f7dd5e8..db122a06edc5 100644 --- a/drivers/base/dma-coherent.c +++ b/drivers/base/dma-coherent.c @@ -261,7 +261,7 @@ int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma, (mem->virt_base + (mem->size << PAGE_SHIFT))) { unsigned long off = vma->vm_pgoff; int start = (vaddr - mem->virt_base) >> PAGE_SHIFT; - int user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; + int user_count = vma_pages(vma); int count = size >> PAGE_SHIFT; *ret = -ENXIO; -- cgit v1.2.3-59-g8ed1b From 95da00e35acf92bb5d39f6f08267de0c1a5c8885 Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Sat, 21 May 2016 18:52:22 +0530 Subject: dma-mapping: use vma_pages(). Replace explicit computation of vma page count by a call to vma_pages() Signed-off-by: Muhammad Falak R Wani Signed-off-by: Greg Kroah-Hartman --- drivers/base/dma-mapping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c index 261420ddfe66..2e318ffa019e 100644 --- a/drivers/base/dma-mapping.c +++ b/drivers/base/dma-mapping.c @@ -247,7 +247,7 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma, { int ret = -ENXIO; #if defined(CONFIG_MMU) && !defined(CONFIG_ARCH_NO_COHERENT_DMA_MMAP) - unsigned long user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; + unsigned long user_count = vma_pages(vma); unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT; unsigned long pfn = page_to_pfn(virt_to_page(cpu_addr)); unsigned long off = vma->vm_pgoff; -- cgit v1.2.3-59-g8ed1b From 59fffa34069d80662b41438b11130771b4e2a897 Mon Sep 17 00:00:00 2001 From: Alex Shi Date: Thu, 25 Aug 2016 16:42:39 +0800 Subject: cpu: clean up register_cpu func This patch could reduce one branch in this function. Also make the code more readble. Signed-off-by: Alex Shi Acked-by: Daniel Lezcano To: linux-kernel@vger.kernel.org To: Greg Kroah-Hartman Cc: linux-pm@vger.kernel.org Cc: Ulf Hansson Cc: Daniel Lezcano Signed-off-by: Greg Kroah-Hartman --- drivers/base/cpu.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 691eeea2f19a..4c28e1a09786 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -371,12 +371,13 @@ int register_cpu(struct cpu *cpu, int num) if (cpu->hotpluggable) cpu->dev.groups = hotplugable_cpu_attr_groups; error = device_register(&cpu->dev); - if (!error) - per_cpu(cpu_sys_devices, num) = &cpu->dev; - if (!error) - register_cpu_under_node(num, cpu_to_node(num)); + if (error) + return error; - return error; + per_cpu(cpu_sys_devices, num) = &cpu->dev; + register_cpu_under_node(num, cpu_to_node(num)); + + return 0; } struct device *get_cpu_device(unsigned cpu) -- cgit v1.2.3-59-g8ed1b From e330b9a6bb35dc7097a4f02cb1ae7b6f96df92af Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Mon, 4 Jul 2016 01:04:24 +0300 Subject: platform: don't return 0 from platform_get_irq[_byname]() on error of_irq_get[_byname]() return 0 iff irq_create_of_mapping() call fails. Returning both error code and 0 on failure is a sign of a misdesigned API, it makes the failure check unnecessarily complex and error prone. We should rely on the platform IRQ resource in this case, not return 0, especially as 0 can be a valid IRQ resource too... Fixes: aff008ad813c ("platform_get_irq: Revert to platform_get_resource if of_irq_get fails") Signed-off-by: Sergei Shtylyov CC: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index f57fff3f268b..44c9d4daf510 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -97,7 +97,7 @@ int platform_get_irq(struct platform_device *dev, unsigned int num) int ret; ret = of_irq_get(dev->dev.of_node, num); - if (ret >= 0 || ret == -EPROBE_DEFER) + if (ret > 0 || ret == -EPROBE_DEFER) return ret; } @@ -175,7 +175,7 @@ int platform_get_irq_byname(struct platform_device *dev, const char *name) int ret; ret = of_irq_get_byname(dev->dev.of_node, name); - if (ret >= 0 || ret == -EPROBE_DEFER) + if (ret > 0 || ret == -EPROBE_DEFER) return ret; } -- cgit v1.2.3-59-g8ed1b From 775115c06091fcfa1189a50aca488fa596839617 Mon Sep 17 00:00:00 2001 From: "Vyacheslav V. Yurkov" Date: Tue, 14 Jun 2016 09:58:37 +0200 Subject: drivers/base dmam_declare_coherent_memory leaks dmam_declare_coherent_memory doesn't take into account the return value of dma_declare_coherent_memory, which leads to incorrect resource handling Signed-off-by: Vyacheslav V. Yurkov Signed-off-by: Greg Kroah-Hartman --- drivers/base/dma-mapping.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c index 2e318ffa019e..8f8b68c80986 100644 --- a/drivers/base/dma-mapping.c +++ b/drivers/base/dma-mapping.c @@ -198,10 +198,13 @@ int dmam_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, rc = dma_declare_coherent_memory(dev, phys_addr, device_addr, size, flags); - if (rc == 0) + if (rc) { devres_add(dev, res); - else + rc = 0; + } else { devres_free(res); + rc = -ENOMEM; + } return rc; } -- cgit v1.2.3-59-g8ed1b From 2c507e464f791327c94d17a0137f00b4717744fc Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Tue, 30 Aug 2016 22:45:34 +0530 Subject: device core: Remove deprecated create_singlethread_workqueue The workqueue "deferred_wq" queues a single work item &deferred_probe_work and hence doesn't require ordering. It is involved in probing devices and is not being used on a memory reclaim path. Hence, it has been converted to use system_wq. System workqueues have been able to handle high level of concurrency for a long time now and hence it's not required to have a singlethreaded workqueue just to gain concurrency. Unlike a dedicated per-cpu workqueue created with create_singlethread_workqueue(), system_wq allows multiple work items to overlap executions even on the same CPU; however, a per-cpu workqueue doesn't have any CPU locality or global ordering guarantee unless the target CPU is explicitly specified and thus the increase of local concurrency shouldn't make any difference. The work item has been flushed in driver_probe_done() to ensure that there are no pending tasks while disconnecting the driver. Signed-off-by: Bhaktipriya Shridhar Acked-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 4910e6db2a34..d22a7260f42b 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -51,7 +51,6 @@ static DEFINE_MUTEX(deferred_probe_mutex); static LIST_HEAD(deferred_probe_pending_list); static LIST_HEAD(deferred_probe_active_list); -static struct workqueue_struct *deferred_wq; static atomic_t deferred_trigger_count = ATOMIC_INIT(0); /* @@ -175,7 +174,7 @@ static void driver_deferred_probe_trigger(void) * Kick the re-probe thread. It may already be scheduled, but it is * safe to kick it again. */ - queue_work(deferred_wq, &deferred_probe_work); + schedule_work(&deferred_probe_work); } /** @@ -211,14 +210,10 @@ void device_unblock_probing(void) */ static int deferred_probe_initcall(void) { - deferred_wq = create_singlethread_workqueue("deferwq"); - if (WARN_ON(!deferred_wq)) - return -ENOMEM; - driver_deferred_probe_enable = true; driver_deferred_probe_trigger(); /* Sort as many dependencies as possible before exiting initcalls */ - flush_workqueue(deferred_wq); + flush_work(&deferred_probe_work); return 0; } late_initcall(deferred_probe_initcall); @@ -481,8 +476,7 @@ int driver_probe_done(void) void wait_for_device_probe(void) { /* wait for the deferred probe workqueue to finish */ - if (driver_deferred_probe_enable) - flush_workqueue(deferred_wq); + flush_work(&deferred_probe_work); /* wait for the known devices to complete their probing */ wait_event(probe_waitqueue, atomic_read(&probe_count) == 0); -- cgit v1.2.3-59-g8ed1b From 86f0e06767dda7863d6d2a8f0b3b857e6ea876a0 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 17 Sep 2016 21:43:01 +0200 Subject: debugfs: introduce a public file_operations accessor This patch introduces an accessor which can be used by the users of debugfs (drivers, fs, ...) to get the original file_operations struct. It also removes the REAL_FOPS_DEREF macro in file.c and converts the code to use the public version. Previously, REAL_FOPS_DEREF was only available within the file.c of debugfs. But having a public getter available for debugfs users is important as some drivers (carl9170 and b43) use the pointer of the original file_operations in conjunction with container_of() within their debugfs implementations. Reviewed-by: Nicolai Stange Signed-off-by: Christian Lamparter Cc: stable # 4.7+ Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/file.c | 13 +++++-------- include/linux/debugfs.h | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 592059f88e04..309f4e9b2419 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -97,9 +97,6 @@ EXPORT_SYMBOL_GPL(debugfs_use_file_finish); #define F_DENTRY(filp) ((filp)->f_path.dentry) -#define REAL_FOPS_DEREF(dentry) \ - ((const struct file_operations *)(dentry)->d_fsdata) - static int open_proxy_open(struct inode *inode, struct file *filp) { const struct dentry *dentry = F_DENTRY(filp); @@ -112,7 +109,7 @@ static int open_proxy_open(struct inode *inode, struct file *filp) goto out; } - real_fops = REAL_FOPS_DEREF(dentry); + real_fops = debugfs_real_fops(filp); real_fops = fops_get(real_fops); if (!real_fops) { /* Huh? Module did not clean up after itself at exit? */ @@ -143,7 +140,7 @@ static ret_type full_proxy_ ## name(proto) \ { \ const struct dentry *dentry = F_DENTRY(filp); \ const struct file_operations *real_fops = \ - REAL_FOPS_DEREF(dentry); \ + debugfs_real_fops(filp); \ int srcu_idx; \ ret_type r; \ \ @@ -176,7 +173,7 @@ static unsigned int full_proxy_poll(struct file *filp, struct poll_table_struct *wait) { const struct dentry *dentry = F_DENTRY(filp); - const struct file_operations *real_fops = REAL_FOPS_DEREF(dentry); + const struct file_operations *real_fops = debugfs_real_fops(filp); int srcu_idx; unsigned int r = 0; @@ -193,7 +190,7 @@ static unsigned int full_proxy_poll(struct file *filp, static int full_proxy_release(struct inode *inode, struct file *filp) { const struct dentry *dentry = F_DENTRY(filp); - const struct file_operations *real_fops = REAL_FOPS_DEREF(dentry); + const struct file_operations *real_fops = debugfs_real_fops(filp); const struct file_operations *proxy_fops = filp->f_op; int r = 0; @@ -241,7 +238,7 @@ static int full_proxy_open(struct inode *inode, struct file *filp) goto out; } - real_fops = REAL_FOPS_DEREF(dentry); + real_fops = debugfs_real_fops(filp); real_fops = fops_get(real_fops); if (!real_fops) { /* Huh? Module did not cleanup after itself at exit? */ diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index 1438e2322d5c..4d3f0d1aec73 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h @@ -45,6 +45,23 @@ extern struct dentry *arch_debugfs_dir; extern struct srcu_struct debugfs_srcu; +/** + * debugfs_real_fops - getter for the real file operation + * @filp: a pointer to a struct file + * + * Must only be called under the protection established by + * debugfs_use_file_start(). + */ +static inline const struct file_operations *debugfs_real_fops(struct file *filp) + __must_hold(&debugfs_srcu) +{ + /* + * Neither the pointer to the struct file_operations, nor its + * contents ever change -- srcu_dereference() is not needed here. + */ + return filp->f_path.dentry->d_fsdata; +} + #if defined(CONFIG_DEBUG_FS) struct dentry *debugfs_create_file(const char *name, umode_t mode, -- cgit v1.2.3-59-g8ed1b From 51b275a6fe5601834b717351d6cbdb89bd1f308b Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 17 Sep 2016 21:43:03 +0200 Subject: b43: fix debugfs crash This patch fixes a crash that happens because b43's debugfs code expects file->f_op to be a pointer to its own b43_debugfs_fops struct. This is no longer the case since commit 9fd4dcece43a ("debugfs: prevent access to possibly dead file_operations at file open") Reviewed-by: Nicolai Stange Signed-off-by: Christian Lamparter Cc: stable # 4.7+ Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/broadcom/b43/debugfs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/broadcom/b43/debugfs.c b/drivers/net/wireless/broadcom/b43/debugfs.c index b4bcd94aff6c..77046384dd80 100644 --- a/drivers/net/wireless/broadcom/b43/debugfs.c +++ b/drivers/net/wireless/broadcom/b43/debugfs.c @@ -524,7 +524,8 @@ static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf, goto out_unlock; } - dfops = container_of(file->f_op, struct b43_debugfs_fops, fops); + dfops = container_of(debugfs_real_fops(file), + struct b43_debugfs_fops, fops); if (!dfops->read) { err = -ENOSYS; goto out_unlock; @@ -585,7 +586,8 @@ static ssize_t b43_debugfs_write(struct file *file, goto out_unlock; } - dfops = container_of(file->f_op, struct b43_debugfs_fops, fops); + dfops = container_of(debugfs_real_fops(file), + struct b43_debugfs_fops, fops); if (!dfops->write) { err = -ENOSYS; goto out_unlock; -- cgit v1.2.3-59-g8ed1b From 9c4a45b17e094a090e96beb1138e34c2a10c6b8c Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 17 Sep 2016 21:43:04 +0200 Subject: b43legacy: fix debugfs crash This patch fixes a crash that happens because b43legacy's debugfs code expects file->f_op to be a pointer to its own b43legacy_debugfs_fops struct. This is no longer the case since commit 9fd4dcece43a ("debugfs: prevent access to possibly dead file_operations at file open") Reviewed-by: Nicolai Stange Signed-off-by: Christian Lamparter Cc: stable # 4.7+ Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/broadcom/b43legacy/debugfs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/broadcom/b43legacy/debugfs.c b/drivers/net/wireless/broadcom/b43legacy/debugfs.c index 090910ea259e..82ef56ed7ca1 100644 --- a/drivers/net/wireless/broadcom/b43legacy/debugfs.c +++ b/drivers/net/wireless/broadcom/b43legacy/debugfs.c @@ -221,7 +221,8 @@ static ssize_t b43legacy_debugfs_read(struct file *file, char __user *userbuf, goto out_unlock; } - dfops = container_of(file->f_op, struct b43legacy_debugfs_fops, fops); + dfops = container_of(debugfs_real_fops(file), + struct b43legacy_debugfs_fops, fops); if (!dfops->read) { err = -ENOSYS; goto out_unlock; @@ -287,7 +288,8 @@ static ssize_t b43legacy_debugfs_write(struct file *file, goto out_unlock; } - dfops = container_of(file->f_op, struct b43legacy_debugfs_fops, fops); + dfops = container_of(debugfs_real_fops(file), + struct b43legacy_debugfs_fops, fops); if (!dfops->write) { err = -ENOSYS; goto out_unlock; -- cgit v1.2.3-59-g8ed1b From 6ee6d1cb391ca85b419f8d18bdfb1f020a5e859c Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Wed, 21 Sep 2016 18:49:36 +0200 Subject: carl9170: fix debugfs crashes Ben Greear reported: > I see lots of instability as soon as I load up the carl9710 NIC. > My application is going to be poking at it's debugfs files... > > BUG: KASAN: slab-out-of-bounds in carl9170_debugfs_read+0xd5/0x2a0 > [carl9170] at addr 0xffff8801bc1208b0 > Read of size 8 by task btserver/5888 > ======================================================================= > BUG kmalloc-256 (Tainted: G W ): kasan: bad access detected > ----------------------------------------------------------------------- > > INFO: Allocated in seq_open+0x50/0x100 age=2690 cpu=2 pid=772 >... This breakage was caused by the introduction of intermediate fops in debugfs by commit 9fd4dcece43a ("debugfs: prevent access to possibly dead file_operations at file open") Thankfully, the original/real fops are still available in d_fsdata. Reported-by: Ben Greear Signed-off-by: Christian Lamparter Cc: stable # 4.7+ Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/ath/carl9170/debug.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c index 6808db433283..ec3a64e5d2bb 100644 --- a/drivers/net/wireless/ath/carl9170/debug.c +++ b/drivers/net/wireless/ath/carl9170/debug.c @@ -75,7 +75,8 @@ static ssize_t carl9170_debugfs_read(struct file *file, char __user *userbuf, if (!ar) return -ENODEV; - dfops = container_of(file->f_op, struct carl9170_debugfs_fops, fops); + dfops = container_of(debugfs_real_fops(file), + struct carl9170_debugfs_fops, fops); if (!dfops->read) return -ENOSYS; @@ -127,7 +128,8 @@ static ssize_t carl9170_debugfs_write(struct file *file, if (!ar) return -ENODEV; - dfops = container_of(file->f_op, struct carl9170_debugfs_fops, fops); + dfops = container_of(debugfs_real_fops(file), + struct carl9170_debugfs_fops, fops); if (!dfops->write) return -ENOSYS; -- cgit v1.2.3-59-g8ed1b From 78618d395b65fadb2937a985308c3a4d2897ade2 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Mon, 19 Sep 2016 10:14:54 +0200 Subject: sysfs print name of undiscoverable attribute group Print the name of an undiscoverable attribute group and not the pointer's address. Signed-off-by: Johannes Thumshirn Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/group.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index dc1358b5ec95..ac2de0ed69ad 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c @@ -233,8 +233,8 @@ void sysfs_remove_group(struct kobject *kobj, kn = kernfs_find_and_get(parent, grp->name); if (!kn) { WARN(!kn, KERN_WARNING - "sysfs group %p not found for kobject '%s'\n", - grp, kobject_name(kobj)); + "sysfs group '%s' not found for kobject '%s'\n", + grp->name, kobject_name(kobj)); return; } } else { -- cgit v1.2.3-59-g8ed1b From 60ca5e0d280b1a51df55c5fc2e5bfe010b344c5a Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 13 Sep 2016 20:32:44 -0700 Subject: driver-core: platform: Catch errors from calls to irq_get_irq_data irq_get_irq_data() can return NULL, which results in a nasty crash. Check its return value before passing it on to irqd_set_trigger_type(). Signed-off-by: Guenter Roeck Reviewed-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 44c9d4daf510..c4af00385502 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -108,9 +108,14 @@ int platform_get_irq(struct platform_device *dev, unsigned int num) * IORESOURCE_BITS correspond 1-to-1 to the IRQF_TRIGGER* * settings. */ - if (r && r->flags & IORESOURCE_BITS) - irqd_set_trigger_type(irq_get_irq_data(r->start), - r->flags & IORESOURCE_BITS); + if (r && r->flags & IORESOURCE_BITS) { + struct irq_data *irqd; + + irqd = irq_get_irq_data(r->start); + if (!irqd) + return -ENXIO; + irqd_set_trigger_type(irqd, r->flags & IORESOURCE_BITS); + } return r ? r->start : -ENXIO; #endif -- cgit v1.2.3-59-g8ed1b From a1a9e5d29854f69a881b4c1e6ac2d6b54f49dfc6 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Wed, 21 Sep 2016 10:27:36 +0100 Subject: debugfs: propagate release() call result The result was being ignored and 0 was always returned. Return the actual result instead. Signed-off-by: Eric Engestrom Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 309f4e9b2419..354e2ab62031 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c @@ -206,7 +206,7 @@ static int full_proxy_release(struct inode *inode, struct file *filp) replace_fops(filp, d_inode(dentry)->i_fop); kfree((void *)proxy_fops); fops_put(real_fops); - return 0; + return r; } static void __full_proxy_fops_init(struct file_operations *proxy_fops, -- cgit v1.2.3-59-g8ed1b From e7604239c1c56430f1b40ebad161b23d44485c30 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 6 Sep 2016 17:42:06 -0700 Subject: MAINTAINERS: extend firmware_class maintainer list I've been reviewing changes proactively, and plan on doing more of this work. I'm doing this early as I should be getting e-mailed about proposed changes. Signed-off-by: Luis R. Rodriguez Acked-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index db814a89599c..4c6587f827d0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4850,6 +4850,7 @@ F: tools/firewire/ FIRMWARE LOADER (request_firmware) M: Ming Lei +M: Luis R. Rodriguez L: linux-kernel@vger.kernel.org S: Maintained F: Documentation/firmware_class/ -- cgit v1.2.3-59-g8ed1b From 9ca5d4fd08d1c560a46ff649221a891065039891 Mon Sep 17 00:00:00 2001 From: "George G. Davis" Date: Wed, 28 Sep 2016 08:51:56 +0100 Subject: drivers: dma-coherent: Fix DMA coherent size for less than page We fix a bug in dma_mmap_from_coherent() that appears when we map non page aligned DMA memory. It cuts off the non aligned part (this is different to dma_alloc_coherent() that always rounds up to full pages). So for mappings of less than a page we get -ENXIO as dma_mmap_from_coherent() assumes we want to map zero pages. Signed-off-by: George G. Davis Signed-off-by: Jiada Wang Signed-off-by: Mark Craske 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 db122a06edc5..2789f7a95b93 100644 --- a/drivers/base/dma-coherent.c +++ b/drivers/base/dma-coherent.c @@ -262,7 +262,7 @@ int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma, unsigned long off = vma->vm_pgoff; int start = (vaddr - mem->virt_base) >> PAGE_SHIFT; int user_count = vma_pages(vma); - int count = size >> PAGE_SHIFT; + int count = PAGE_ALIGN(size) >> PAGE_SHIFT; *ret = -ENXIO; if (off < count && user_count <= count - off) { -- cgit v1.2.3-59-g8ed1b From dd01c75f1df311793de6ef217c72036552000c9a Mon Sep 17 00:00:00 2001 From: Bastian Hecht Date: Wed, 28 Sep 2016 08:51:57 +0100 Subject: drivers: dma-coherent: Move spinlock in dma_alloc_from_coherent() We don't need to hold the spinlock while zeroing the allocated memory. In case we handle big buffers this is a severe issue as other CPUs might be spinning half a second or longer. Signed-off-by: Bastian Hecht Signed-off-by: George G. Davis Signed-off-by: Mark Craske Signed-off-by: Greg Kroah-Hartman --- drivers/base/dma-coherent.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c index 2789f7a95b93..640a7e63c453 100644 --- a/drivers/base/dma-coherent.c +++ b/drivers/base/dma-coherent.c @@ -165,6 +165,7 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size, int order = get_order(size); unsigned long flags; int pageno; + int dma_memory_map; if (!dev) return 0; @@ -187,11 +188,12 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size, */ *dma_handle = mem->device_base + (pageno << PAGE_SHIFT); *ret = mem->virt_base + (pageno << PAGE_SHIFT); - if (mem->flags & DMA_MEMORY_MAP) + dma_memory_map = (mem->flags & DMA_MEMORY_MAP); + spin_unlock_irqrestore(&mem->spinlock, flags); + if (dma_memory_map) memset(*ret, 0, size); else memset_io(*ret, 0, size); - spin_unlock_irqrestore(&mem->spinlock, flags); return 1; -- cgit v1.2.3-59-g8ed1b