Pull driver core deferred probe fix from Grant Likely: "Drivercore race condition fix (exposed by devicetree) This branch fixes a bug where a device can get stuck in the deferred list even though all its dependencies are met. The bug has existed for a long time, but new platform conversions to device tree have exposed it. This patch is needed to get those platforms working. This was the pending bug fix I mentioned in my previous pull request. Normally this would go through Greg's tree seeing that it is a drivercore change, but devicetree exposes the problem. I've discussed with Greg and he okayed me asking you to pull directly" * tag 'dt-for-linus' of git://git.secretlab.ca/git/linux: drivercore: deferral race condition fix
Unified · Split
| @@ -52,6 +52,7 @@ static DEFINE_MUTEX(deferred_probe_mutex); · 51 unmodified lines | ||
| 52 | 52 | static LIST_HEAD(deferred_probe_pending_list); |
| 53 | 53 | static LIST_HEAD(deferred_probe_active_list); |
| 54 | 54 | static struct workqueue_struct *deferred_wq; |
| 55 | +static atomic_t deferred_trigger_count = ATOMIC_INIT(0); | |
| 55 | 56 | |
| 56 | 57 | /** |
| 57 | 58 | * deferred_probe_work_func() - Retry probing devices in the active list. |
| @@ -135,6 +136,17 @@ static bool driver_deferred_probe_enable = false; · 77 unmodified lines | ||
| 135 | 136 | * This functions moves all devices from the pending list to the active |
| 136 | 137 | * list and schedules the deferred probe workqueue to process them. It |
| 137 | 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 | 151 | static void driver_deferred_probe_trigger(void) |
| 140 | 152 | { |
| @@ -147,6 +159,7 @@ static void driver_deferred_probe_trigger(void) · 6 unmodified lines | ||
| 147 | 159 | * into the active list so they can be retried by the workqueue |
| 148 | 160 | */ |
| 149 | 161 | mutex_lock(&deferred_probe_mutex); |
| 162 | + atomic_inc(&deferred_trigger_count); | |
| 150 | 163 | list_splice_tail_init(&deferred_probe_pending_list, |
| 151 | 164 | &deferred_probe_active_list); |
| 152 | 165 | mutex_unlock(&deferred_probe_mutex); |
| @@ -265,6 +278,7 @@ static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue); · 112 unmodified lines | ||
| 265 | 278 | static int really_probe(struct device *dev, struct device_driver *drv) |
| 266 | 279 | { |
| 267 | 280 | int ret = 0; |
| 281 | + int local_trigger_count = atomic_read(&deferred_trigger_count); | |
| 268 | 282 | |
| 269 | 283 | atomic_inc(&probe_count); |
| 270 | 284 | pr_debug("bus: '%s': %s: probing driver %s with device %s\n", |
| @@ -310,6 +324,9 @@ probe_failed: · 39 unmodified lines | ||
| 310 | 324 | /* Driver requested deferred probing */ |
| 311 | 325 | dev_info(dev, "Driver %s requests probe deferral\n", drv->name); |
| 312 | 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 | 330 | } else if (ret != -ENODEV && ret != -ENXIO) { |
| 314 | 331 | /* driver matched but the probe failed */ |
| 315 | 332 | printk(KERN_WARNING |