diff options
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/core.c | 33 | ||||
-rw-r--r-- | drivers/base/dd.c | 21 | ||||
-rw-r--r-- | drivers/base/platform.c | 7 | ||||
-rw-r--r-- | drivers/base/topology.c | 3 |
4 files changed, 26 insertions, 38 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index 0dd65281cc65..20da3ad1696b 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -614,39 +614,6 @@ void device_remove_bin_file(struct device *dev, | |||
614 | } | 614 | } |
615 | EXPORT_SYMBOL_GPL(device_remove_bin_file); | 615 | EXPORT_SYMBOL_GPL(device_remove_bin_file); |
616 | 616 | ||
617 | /** | ||
618 | * device_schedule_callback_owner - helper to schedule a callback for a device | ||
619 | * @dev: device. | ||
620 | * @func: callback function to invoke later. | ||
621 | * @owner: module owning the callback routine | ||
622 | * | ||
623 | * Attribute methods must not unregister themselves or their parent device | ||
624 | * (which would amount to the same thing). Attempts to do so will deadlock, | ||
625 | * since unregistration is mutually exclusive with driver callbacks. | ||
626 | * | ||
627 | * Instead methods can call this routine, which will attempt to allocate | ||
628 | * and schedule a workqueue request to call back @func with @dev as its | ||
629 | * argument in the workqueue's process context. @dev will be pinned until | ||
630 | * @func returns. | ||
631 | * | ||
632 | * This routine is usually called via the inline device_schedule_callback(), | ||
633 | * which automatically sets @owner to THIS_MODULE. | ||
634 | * | ||
635 | * Returns 0 if the request was submitted, -ENOMEM if storage could not | ||
636 | * be allocated, -ENODEV if a reference to @owner isn't available. | ||
637 | * | ||
638 | * NOTE: This routine won't work if CONFIG_SYSFS isn't set! It uses an | ||
639 | * underlying sysfs routine (since it is intended for use by attribute | ||
640 | * methods), and if sysfs isn't available you'll get nothing but -ENOSYS. | ||
641 | */ | ||
642 | int device_schedule_callback_owner(struct device *dev, | ||
643 | void (*func)(struct device *), struct module *owner) | ||
644 | { | ||
645 | return sysfs_schedule_callback(&dev->kobj, | ||
646 | (void (*)(void *)) func, dev, owner); | ||
647 | } | ||
648 | EXPORT_SYMBOL_GPL(device_schedule_callback_owner); | ||
649 | |||
650 | static void klist_children_get(struct klist_node *n) | 617 | static void klist_children_get(struct klist_node *n) |
651 | { | 618 | { |
652 | struct device_private *p = to_device_private_parent(n); | 619 | struct device_private *p = to_device_private_parent(n); |
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 06051767393f..62ec61e8f84a 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c | |||
@@ -52,6 +52,7 @@ static DEFINE_MUTEX(deferred_probe_mutex); | |||
52 | static LIST_HEAD(deferred_probe_pending_list); | 52 | static LIST_HEAD(deferred_probe_pending_list); |
53 | static LIST_HEAD(deferred_probe_active_list); | 53 | static LIST_HEAD(deferred_probe_active_list); |
54 | static struct workqueue_struct *deferred_wq; | 54 | static struct workqueue_struct *deferred_wq; |
55 | static atomic_t deferred_trigger_count = ATOMIC_INIT(0); | ||
55 | 56 | ||
56 | /** | 57 | /** |
57 | * deferred_probe_work_func() - Retry probing devices in the active list. | 58 | * deferred_probe_work_func() - Retry probing devices in the active list. |
@@ -135,6 +136,17 @@ static bool driver_deferred_probe_enable = false; | |||
135 | * This functions moves all devices from the pending list to the active | 136 | * This functions moves all devices from the pending list to the active |
136 | * list and schedules the deferred probe workqueue to process them. It | 137 | * list and schedules the deferred probe workqueue to process them. It |
137 | * should be called anytime a driver is successfully bound to a device. | 138 | * should be called anytime a driver is successfully bound to a device. |
139 | * | ||
140 | * Note, there is a race condition in multi-threaded probe. In the case where | ||
141 | * more than one device is probing at the same time, it is possible for one | ||
142 | * probe to complete successfully while another is about to defer. If the second | ||
143 | * depends on the first, then it will get put on the pending list after the | ||
144 | * trigger event has already occured and will be stuck there. | ||
145 | * | ||
146 | * The atomic 'deferred_trigger_count' is used to determine if a successful | ||
147 | * trigger has occurred in the midst of probing a driver. If the trigger count | ||
148 | * changes in the midst of a probe, then deferred processing should be triggered | ||
149 | * again. | ||
138 | */ | 150 | */ |
139 | static void driver_deferred_probe_trigger(void) | 151 | static void driver_deferred_probe_trigger(void) |
140 | { | 152 | { |
@@ -147,6 +159,7 @@ static void driver_deferred_probe_trigger(void) | |||
147 | * into the active list so they can be retried by the workqueue | 159 | * into the active list so they can be retried by the workqueue |
148 | */ | 160 | */ |
149 | mutex_lock(&deferred_probe_mutex); | 161 | mutex_lock(&deferred_probe_mutex); |
162 | atomic_inc(&deferred_trigger_count); | ||
150 | list_splice_tail_init(&deferred_probe_pending_list, | 163 | list_splice_tail_init(&deferred_probe_pending_list, |
151 | &deferred_probe_active_list); | 164 | &deferred_probe_active_list); |
152 | mutex_unlock(&deferred_probe_mutex); | 165 | mutex_unlock(&deferred_probe_mutex); |
@@ -187,8 +200,8 @@ static void driver_bound(struct device *dev) | |||
187 | return; | 200 | return; |
188 | } | 201 | } |
189 | 202 | ||
190 | pr_debug("driver: '%s': %s: bound to device '%s'\n", dev_name(dev), | 203 | pr_debug("driver: '%s': %s: bound to device '%s'\n", dev->driver->name, |
191 | __func__, dev->driver->name); | 204 | __func__, dev_name(dev)); |
192 | 205 | ||
193 | klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices); | 206 | klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices); |
194 | 207 | ||
@@ -265,6 +278,7 @@ static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue); | |||
265 | static int really_probe(struct device *dev, struct device_driver *drv) | 278 | static int really_probe(struct device *dev, struct device_driver *drv) |
266 | { | 279 | { |
267 | int ret = 0; | 280 | int ret = 0; |
281 | int local_trigger_count = atomic_read(&deferred_trigger_count); | ||
268 | 282 | ||
269 | atomic_inc(&probe_count); | 283 | atomic_inc(&probe_count); |
270 | pr_debug("bus: '%s': %s: probing driver %s with device %s\n", | 284 | pr_debug("bus: '%s': %s: probing driver %s with device %s\n", |
@@ -310,6 +324,9 @@ probe_failed: | |||
310 | /* Driver requested deferred probing */ | 324 | /* Driver requested deferred probing */ |
311 | dev_info(dev, "Driver %s requests probe deferral\n", drv->name); | 325 | dev_info(dev, "Driver %s requests probe deferral\n", drv->name); |
312 | driver_deferred_probe_add(dev); | 326 | driver_deferred_probe_add(dev); |
327 | /* Did a trigger occur while probing? Need to re-trigger if yes */ | ||
328 | if (local_trigger_count != atomic_read(&deferred_trigger_count)) | ||
329 | driver_deferred_probe_trigger(); | ||
313 | } else if (ret != -ENODEV && ret != -ENXIO) { | 330 | } else if (ret != -ENODEV && ret != -ENXIO) { |
314 | /* driver matched but the probe failed */ | 331 | /* driver matched but the probe failed */ |
315 | printk(KERN_WARNING | 332 | printk(KERN_WARNING |
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index e714709704e4..5b47210889e0 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/string.h> | 13 | #include <linux/string.h> |
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/of_device.h> | 15 | #include <linux/of_device.h> |
16 | #include <linux/of_irq.h> | ||
16 | #include <linux/module.h> | 17 | #include <linux/module.h> |
17 | #include <linux/init.h> | 18 | #include <linux/init.h> |
18 | #include <linux/dma-mapping.h> | 19 | #include <linux/dma-mapping.h> |
@@ -87,7 +88,11 @@ int platform_get_irq(struct platform_device *dev, unsigned int num) | |||
87 | return -ENXIO; | 88 | return -ENXIO; |
88 | return dev->archdata.irqs[num]; | 89 | return dev->archdata.irqs[num]; |
89 | #else | 90 | #else |
90 | struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num); | 91 | struct resource *r; |
92 | if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node) | ||
93 | return of_irq_get(dev->dev.of_node, num); | ||
94 | |||
95 | r = platform_get_resource(dev, IORESOURCE_IRQ, num); | ||
91 | 96 | ||
92 | return r ? r->start : -ENXIO; | 97 | return r ? r->start : -ENXIO; |
93 | #endif | 98 | #endif |
diff --git a/drivers/base/topology.c b/drivers/base/topology.c index bbcbd3c43926..be7c1fb7c0c9 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c | |||
@@ -39,8 +39,7 @@ | |||
39 | static ssize_t show_##name(struct device *dev, \ | 39 | static ssize_t show_##name(struct device *dev, \ |
40 | struct device_attribute *attr, char *buf) \ | 40 | struct device_attribute *attr, char *buf) \ |
41 | { \ | 41 | { \ |
42 | unsigned int cpu = dev->id; \ | 42 | return sprintf(buf, "%d\n", topology_##name(dev->id)); \ |
43 | return sprintf(buf, "%d\n", topology_##name(cpu)); \ | ||
44 | } | 43 | } |
45 | 44 | ||
46 | #if defined(topology_thread_cpumask) || defined(topology_core_cpumask) || \ | 45 | #if defined(topology_thread_cpumask) || defined(topology_core_cpumask) || \ |