• Adrian Hunter's avatar
    PM: runtime: Fix race getting/putting suppliers at probe · 9dfacc54
    Adrian Hunter authored
    pm_runtime_put_suppliers() must not decrement rpm_active unless the
    consumer is suspended. That is because, otherwise, it could suspend
    suppliers for an active consumer.
    
    That can happen as follows:
    
     static int driver_probe_device(struct device_driver *drv, struct device *dev)
     {
    	int ret = 0;
    
    	if (!device_is_registered(dev))
    		return -ENODEV;
    
    	dev->can_match = true;
    	pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
    		 drv->bus->name, __func__, dev_name(dev), drv->name);
    
    	pm_runtime_get_suppliers(dev);
    	if (dev->parent)
    		pm_runtime_get_sync(dev->parent);
    
     At this point, dev can runtime suspend so rpm_put_suppliers() can run,
     rpm_active becomes 1 (the lowest value).
    
    	pm_runtime_barrier(dev);
    	if (initcall_debug)
    		ret = really_probe_debug(dev, drv);
    	else
    		ret = really_probe(dev, drv);
    
     Probe callback can have runtime resumed dev, and then runtime put
     so dev is awaiting autosuspend, but rpm_active is 2.
    
    	pm_request_idle(dev);
    
    	if (dev->parent)
    		pm_runtime_put(dev->parent);
    
    	pm_runtime_put_suppliers(dev);
    
     Now pm_runtime_put_suppliers() will put the supplier
     i.e. rpm_active 2 -> 1, but consumer can still be active.
    
    	return ret;
     }
    
    Fix by checking the runtime status. For any status other than
    RPM_SUSPENDED, rpm_active can be considered to be "owned" by
    rpm_[get/put]_suppliers() and pm_runtime_put_suppliers() need do nothing.
    Reported-by: default avatarAsutosh Das <asutoshd@codeaurora.org>
    Fixes: 4c06c4e6 ("driver core: Fix possible supplier PM-usage counter imbalance")
    Signed-off-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
    Cc: 5.1+ <stable@vger.kernel.org> # 5.1+
    Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
    9dfacc54
runtime.c 50.8 KB