Skip to content

Commit

Permalink
Merge tag 'driver-core-4.9-rc1' of git://git.kernel.org/pub/scm/linux…
Browse files Browse the repository at this point in the history
…/kernel/git/gregkh/driver-core

Pull driver core updates from Greg KH:
 "Here are the "big" driver core patches for 4.9-rc1. Also in here are a
  number of debugfs fixes that cropped up due to the changes that
  happened in 4.8 for that filesystem. Overall, nothing major, just a
  few fixes and cleanups.

  All of these have been in linux-next with no reported issues"

* tag 'driver-core-4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (23 commits)
  drivers: dma-coherent: Move spinlock in dma_alloc_from_coherent()
  drivers: dma-coherent: Fix DMA coherent size for less than page
  MAINTAINERS: extend firmware_class maintainer list
  debugfs: propagate release() call result
  driver-core: platform: Catch errors from calls to irq_get_irq_data
  sysfs print name of undiscoverable attribute group
  carl9170: fix debugfs crashes
  b43legacy: fix debugfs crash
  b43: fix debugfs crash
  debugfs: introduce a public file_operations accessor
  device core: Remove deprecated create_singlethread_workqueue
  drivers/base dmam_declare_coherent_memory leaks
  platform: don't return 0 from platform_get_irq[_byname]() on error
  cpu: clean up register_cpu func
  dma-mapping: use vma_pages().
  drivers: dma-coherent: use vma_pages().
  attribute_container: Fix typo
  base: soc: make it explicitly non-modular
  drivers: base: dma-mapping: page align the size when unmap_kernel_range
  platform driver: fix use-after-free in platform_device_del()
  ...
  • Loading branch information
Linus Torvalds committed Oct 4, 2016
2 parents 7a53eea + dd01c75 commit 9929780
Show file tree
Hide file tree
Showing 17 changed files with 132 additions and 70 deletions.
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -4866,6 +4866,7 @@ F: tools/firewire/

FIRMWARE LOADER (request_firmware)
M: Ming Lei <ming.lei@canonical.com>
M: Luis R. Rodriguez <mcgrof@kernel.org>
L: linux-kernel@vger.kernel.org
S: Maintained
F: Documentation/firmware_class/
Expand Down
10 changes: 10 additions & 0 deletions drivers/base/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion drivers/base/attribute_container.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down
39 changes: 29 additions & 10 deletions drivers/base/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -836,23 +836,36 @@ 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);
kobject_put(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);
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -1154,9 +1170,10 @@ int device_add(struct device *dev)
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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1277,8 +1295,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);
Expand Down
11 changes: 6 additions & 5 deletions drivers/base/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
33 changes: 24 additions & 9 deletions drivers/base/dd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

/*
Expand Down Expand Up @@ -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);
}

/**
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -329,6 +324,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) {
/*
Expand All @@ -346,6 +342,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 */
Expand Down Expand Up @@ -383,6 +380,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)
Expand Down Expand Up @@ -460,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);
Expand Down
10 changes: 6 additions & 4 deletions drivers/base/dma-coherent.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -261,8 +263,8 @@ 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 count = size >> PAGE_SHIFT;
int user_count = vma_pages(vma);
int count = PAGE_ALIGN(size) >> PAGE_SHIFT;

*ret = -ENXIO;
if (off < count && user_count <= count - off) {
Expand Down
11 changes: 7 additions & 4 deletions drivers/base/dma-mapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -247,7 +250,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;
Expand Down Expand Up @@ -334,7 +337,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
18 changes: 11 additions & 7 deletions drivers/base/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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
Expand Down Expand Up @@ -175,7 +180,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;
}

Expand Down Expand Up @@ -434,6 +439,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) {
Expand All @@ -446,8 +452,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);
Expand Down
9 changes: 0 additions & 9 deletions drivers/base/soc.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
*/

#include <linux/sysfs.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/stat.h>
#include <linux/slab.h>
Expand Down Expand Up @@ -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);
6 changes: 4 additions & 2 deletions drivers/net/wireless/ath/carl9170/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
Loading

0 comments on commit 9929780

Please sign in to comment.