diff options
-rw-r--r-- | drivers/base/base.h | 1 | ||||
-rw-r--r-- | drivers/base/core.c | 2 | ||||
-rw-r--r-- | drivers/base/dd.c | 138 | ||||
-rw-r--r-- | include/linux/device.h | 5 | ||||
-rw-r--r-- | include/linux/errno.h | 1 |
5 files changed, 146 insertions, 1 deletions
diff --git a/drivers/base/base.h b/drivers/base/base.h index b858dfd9a37c..2c13deae5f82 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h | |||
@@ -105,6 +105,7 @@ extern void bus_remove_driver(struct device_driver *drv); | |||
105 | 105 | ||
106 | extern void driver_detach(struct device_driver *drv); | 106 | extern void driver_detach(struct device_driver *drv); |
107 | extern int driver_probe_device(struct device_driver *drv, struct device *dev); | 107 | extern int driver_probe_device(struct device_driver *drv, struct device *dev); |
108 | extern void driver_deferred_probe_del(struct device *dev); | ||
108 | static inline int driver_match_device(struct device_driver *drv, | 109 | static inline int driver_match_device(struct device_driver *drv, |
109 | struct device *dev) | 110 | struct device *dev) |
110 | { | 111 | { |
diff --git a/drivers/base/core.c b/drivers/base/core.c index 74dda4f697f9..d4ff7adce38c 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -644,6 +644,7 @@ void device_initialize(struct device *dev) | |||
644 | { | 644 | { |
645 | dev->kobj.kset = devices_kset; | 645 | dev->kobj.kset = devices_kset; |
646 | kobject_init(&dev->kobj, &device_ktype); | 646 | kobject_init(&dev->kobj, &device_ktype); |
647 | INIT_LIST_HEAD(&dev->deferred_probe); | ||
647 | INIT_LIST_HEAD(&dev->dma_pools); | 648 | INIT_LIST_HEAD(&dev->dma_pools); |
648 | mutex_init(&dev->mutex); | 649 | mutex_init(&dev->mutex); |
649 | lockdep_set_novalidate_class(&dev->mutex); | 650 | lockdep_set_novalidate_class(&dev->mutex); |
@@ -1188,6 +1189,7 @@ void device_del(struct device *dev) | |||
1188 | device_remove_file(dev, &uevent_attr); | 1189 | device_remove_file(dev, &uevent_attr); |
1189 | device_remove_attrs(dev); | 1190 | device_remove_attrs(dev); |
1190 | bus_remove_device(dev); | 1191 | bus_remove_device(dev); |
1192 | driver_deferred_probe_del(dev); | ||
1191 | 1193 | ||
1192 | /* | 1194 | /* |
1193 | * Some platform devices are driven without driver attached | 1195 | * Some platform devices are driven without driver attached |
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 142e3d600f14..442b7641a086 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c | |||
@@ -28,6 +28,133 @@ | |||
28 | #include "base.h" | 28 | #include "base.h" |
29 | #include "power/power.h" | 29 | #include "power/power.h" |
30 | 30 | ||
31 | /* | ||
32 | * Deferred Probe infrastructure. | ||
33 | * | ||
34 | * Sometimes driver probe order matters, but the kernel doesn't always have | ||
35 | * dependency information which means some drivers will get probed before a | ||
36 | * resource it depends on is available. For example, an SDHCI driver may | ||
37 | * first need a GPIO line from an i2c GPIO controller before it can be | ||
38 | * initialized. If a required resource is not available yet, a driver can | ||
39 | * request probing to be deferred by returning -EPROBE_DEFER from its probe hook | ||
40 | * | ||
41 | * Deferred probe maintains two lists of devices, a pending list and an active | ||
42 | * list. A driver returning -EPROBE_DEFER causes the device to be added to the | ||
43 | * pending list. A successful driver probe will trigger moving all devices | ||
44 | * from the pending to the active list so that the workqueue will eventually | ||
45 | * retry them. | ||
46 | * | ||
47 | * The deferred_probe_mutex must be held any time the deferred_probe_*_list | ||
48 | * of the (struct device*)->deferred_probe pointers are manipulated | ||
49 | */ | ||
50 | static DEFINE_MUTEX(deferred_probe_mutex); | ||
51 | static LIST_HEAD(deferred_probe_pending_list); | ||
52 | static LIST_HEAD(deferred_probe_active_list); | ||
53 | static struct workqueue_struct *deferred_wq; | ||
54 | |||
55 | /** | ||
56 | * deferred_probe_work_func() - Retry probing devices in the active list. | ||
57 | */ | ||
58 | static void deferred_probe_work_func(struct work_struct *work) | ||
59 | { | ||
60 | struct device *dev; | ||
61 | /* | ||
62 | * This block processes every device in the deferred 'active' list. | ||
63 | * Each device is removed from the active list and passed to | ||
64 | * bus_probe_device() to re-attempt the probe. The loop continues | ||
65 | * until every device in the active list is removed and retried. | ||
66 | * | ||
67 | * Note: Once the device is removed from the list and the mutex is | ||
68 | * released, it is possible for the device get freed by another thread | ||
69 | * and cause a illegal pointer dereference. This code uses | ||
70 | * get/put_device() to ensure the device structure cannot disappear | ||
71 | * from under our feet. | ||
72 | */ | ||
73 | mutex_lock(&deferred_probe_mutex); | ||
74 | while (!list_empty(&deferred_probe_active_list)) { | ||
75 | dev = list_first_entry(&deferred_probe_active_list, | ||
76 | typeof(*dev), deferred_probe); | ||
77 | list_del_init(&dev->deferred_probe); | ||
78 | |||
79 | get_device(dev); | ||
80 | |||
81 | /* Drop the mutex while probing each device; the probe path | ||
82 | * may manipulate the deferred list */ | ||
83 | mutex_unlock(&deferred_probe_mutex); | ||
84 | dev_dbg(dev, "Retrying from deferred list\n"); | ||
85 | bus_probe_device(dev); | ||
86 | mutex_lock(&deferred_probe_mutex); | ||
87 | |||
88 | put_device(dev); | ||
89 | } | ||
90 | mutex_unlock(&deferred_probe_mutex); | ||
91 | } | ||
92 | static DECLARE_WORK(deferred_probe_work, deferred_probe_work_func); | ||
93 | |||
94 | static void driver_deferred_probe_add(struct device *dev) | ||
95 | { | ||
96 | mutex_lock(&deferred_probe_mutex); | ||
97 | if (list_empty(&dev->deferred_probe)) { | ||
98 | dev_dbg(dev, "Added to deferred list\n"); | ||
99 | list_add(&dev->deferred_probe, &deferred_probe_pending_list); | ||
100 | } | ||
101 | mutex_unlock(&deferred_probe_mutex); | ||
102 | } | ||
103 | |||
104 | void driver_deferred_probe_del(struct device *dev) | ||
105 | { | ||
106 | mutex_lock(&deferred_probe_mutex); | ||
107 | if (!list_empty(&dev->deferred_probe)) { | ||
108 | dev_dbg(dev, "Removed from deferred list\n"); | ||
109 | list_del_init(&dev->deferred_probe); | ||
110 | } | ||
111 | mutex_unlock(&deferred_probe_mutex); | ||
112 | } | ||
113 | |||
114 | static bool driver_deferred_probe_enable = false; | ||
115 | /** | ||
116 | * driver_deferred_probe_trigger() - Kick off re-probing deferred devices | ||
117 | * | ||
118 | * This functions moves all devices from the pending list to the active | ||
119 | * list and schedules the deferred probe workqueue to process them. It | ||
120 | * should be called anytime a driver is successfully bound to a device. | ||
121 | */ | ||
122 | static void driver_deferred_probe_trigger(void) | ||
123 | { | ||
124 | if (!driver_deferred_probe_enable) | ||
125 | return; | ||
126 | |||
127 | /* A successful probe means that all the devices in the pending list | ||
128 | * should be triggered to be reprobed. Move all the deferred devices | ||
129 | * into the active list so they can be retried by the workqueue */ | ||
130 | mutex_lock(&deferred_probe_mutex); | ||
131 | list_splice_tail_init(&deferred_probe_pending_list, | ||
132 | &deferred_probe_active_list); | ||
133 | mutex_unlock(&deferred_probe_mutex); | ||
134 | |||
135 | /* Kick the re-probe thread. It may already be scheduled, but | ||
136 | * it is safe to kick it again. */ | ||
137 | queue_work(deferred_wq, &deferred_probe_work); | ||
138 | } | ||
139 | |||
140 | /** | ||
141 | * deferred_probe_initcall() - Enable probing of deferred devices | ||
142 | * | ||
143 | * We don't want to get in the way when the bulk of drivers are getting probed. | ||
144 | * Instead, this initcall makes sure that deferred probing is delayed until | ||
145 | * late_initcall time. | ||
146 | */ | ||
147 | static int deferred_probe_initcall(void) | ||
148 | { | ||
149 | deferred_wq = create_singlethread_workqueue("deferwq"); | ||
150 | if (WARN_ON(!deferred_wq)) | ||
151 | return -ENOMEM; | ||
152 | |||
153 | driver_deferred_probe_enable = true; | ||
154 | driver_deferred_probe_trigger(); | ||
155 | return 0; | ||
156 | } | ||
157 | late_initcall(deferred_probe_initcall); | ||
31 | 158 | ||
32 | static void driver_bound(struct device *dev) | 159 | static void driver_bound(struct device *dev) |
33 | { | 160 | { |
@@ -42,6 +169,11 @@ static void driver_bound(struct device *dev) | |||
42 | 169 | ||
43 | klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices); | 170 | klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices); |
44 | 171 | ||
172 | /* Make sure the device is no longer in one of the deferred lists | ||
173 | * and kick off retrying all pending devices */ | ||
174 | driver_deferred_probe_del(dev); | ||
175 | driver_deferred_probe_trigger(); | ||
176 | |||
45 | if (dev->bus) | 177 | if (dev->bus) |
46 | blocking_notifier_call_chain(&dev->bus->p->bus_notifier, | 178 | blocking_notifier_call_chain(&dev->bus->p->bus_notifier, |
47 | BUS_NOTIFY_BOUND_DRIVER, dev); | 179 | BUS_NOTIFY_BOUND_DRIVER, dev); |
@@ -142,7 +274,11 @@ probe_failed: | |||
142 | driver_sysfs_remove(dev); | 274 | driver_sysfs_remove(dev); |
143 | dev->driver = NULL; | 275 | dev->driver = NULL; |
144 | 276 | ||
145 | if (ret != -ENODEV && ret != -ENXIO) { | 277 | if (ret == -EPROBE_DEFER) { |
278 | /* Driver requested deferred probing */ | ||
279 | dev_info(dev, "Driver %s requests probe deferral\n", drv->name); | ||
280 | driver_deferred_probe_add(dev); | ||
281 | } else if (ret != -ENODEV && ret != -ENXIO) { | ||
146 | /* driver matched but the probe failed */ | 282 | /* driver matched but the probe failed */ |
147 | printk(KERN_WARNING | 283 | printk(KERN_WARNING |
148 | "%s: probe of %s failed with error %d\n", | 284 | "%s: probe of %s failed with error %d\n", |
diff --git a/include/linux/device.h b/include/linux/device.h index f62e21689fdd..22d6938ddbb4 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -585,6 +585,10 @@ struct device_dma_parameters { | |||
585 | * @mutex: Mutex to synchronize calls to its driver. | 585 | * @mutex: Mutex to synchronize calls to its driver. |
586 | * @bus: Type of bus device is on. | 586 | * @bus: Type of bus device is on. |
587 | * @driver: Which driver has allocated this | 587 | * @driver: Which driver has allocated this |
588 | * @deferred_probe: entry in deferred_probe_list which is used to retry the | ||
589 | * binding of drivers which were unable to get all the resources | ||
590 | * needed by the device; typically because it depends on another | ||
591 | * driver getting probed first. | ||
588 | * @platform_data: Platform data specific to the device. | 592 | * @platform_data: Platform data specific to the device. |
589 | * Example: For devices on custom boards, as typical of embedded | 593 | * Example: For devices on custom boards, as typical of embedded |
590 | * and SOC based hardware, Linux often uses platform_data to point | 594 | * and SOC based hardware, Linux often uses platform_data to point |
@@ -644,6 +648,7 @@ struct device { | |||
644 | struct bus_type *bus; /* type of bus device is on */ | 648 | struct bus_type *bus; /* type of bus device is on */ |
645 | struct device_driver *driver; /* which driver has allocated this | 649 | struct device_driver *driver; /* which driver has allocated this |
646 | device */ | 650 | device */ |
651 | struct list_head deferred_probe; | ||
647 | void *platform_data; /* Platform specific data, device | 652 | void *platform_data; /* Platform specific data, device |
648 | core doesn't touch it */ | 653 | core doesn't touch it */ |
649 | struct dev_pm_info power; | 654 | struct dev_pm_info power; |
diff --git a/include/linux/errno.h b/include/linux/errno.h index 46685832ed99..2d09bfa5c262 100644 --- a/include/linux/errno.h +++ b/include/linux/errno.h | |||
@@ -16,6 +16,7 @@ | |||
16 | #define ERESTARTNOHAND 514 /* restart if no handler.. */ | 16 | #define ERESTARTNOHAND 514 /* restart if no handler.. */ |
17 | #define ENOIOCTLCMD 515 /* No ioctl command */ | 17 | #define ENOIOCTLCMD 515 /* No ioctl command */ |
18 | #define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */ | 18 | #define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */ |
19 | #define EPROBE_DEFER 517 /* Driver requests probe retry */ | ||
19 | 20 | ||
20 | /* Defined for the NFSv3 protocol */ | 21 | /* Defined for the NFSv3 protocol */ |
21 | #define EBADHANDLE 521 /* Illegal NFS file handle */ | 22 | #define EBADHANDLE 521 /* Illegal NFS file handle */ |