@@ -1817,6 +1817,12 @@
* it again during the complete phase.
*/
pm_runtime_get_noresume(dev);
+ /*
+ * Devices that have had runtime PM disabled recently may need to be
+ * handled as though they have never supported it, so arrange for
+ * detecting that situation.
+ */
+ pm_runtime_kick_last_status(dev);
if (dev->power.syscore)
return 0;
@@ -1480,6 +1480,9 @@
if (dev->power.disable_depth > 0) {
dev->power.disable_depth++;
+ if (dev->power.last_status == RPM_UNKNOWN)
+ dev->power.last_status = RPM_INVALID;
+
goto out;
}
@@ -1568,6 +1571,28 @@
EXPORT_SYMBOL_GPL(devm_pm_runtime_enable);
/**
+ * pm_runtime_kick_last_status - Start runtime PM support verification.
+ * @dev: Target device.
+ *
+ * If runtime PM is currently disabled for @dev, but it has been enabled at one
+ * point, change power.last_status for it to RPM_UNKNOWN, and if it is still
+ * RPM_UNKNOWN when __pm_runtime_disabled() is called for @dev next time, it
+ * will be changed to RPM_INVALID indicating no runtime PM support going
+ * forward until pm_runtime_enable() is called for @dev.
+ *
+ * This function is used by the PM core.
+ */
+void pm_runtime_kick_last_status(struct device *dev)
+{
+ spin_lock_irq(&dev->power.lock);
+
+ if (dev->power.disable_depth && dev->power.last_status != RPM_INVALID)
+ dev->power.last_status = RPM_UNKNOWN;
+
+ spin_unlock_irq(&dev->power.lock);
+}
+
+/**
* pm_runtime_forbid - Block runtime PM of a device.
* @dev: Device to handle.
*
@@ -597,6 +597,7 @@
RPM_RESUMING,
RPM_SUSPENDED,
RPM_SUSPENDING,
+ RPM_UNKNOWN,
};
/*
@@ -80,6 +80,7 @@
extern int pm_runtime_barrier(struct device *dev);
extern void pm_runtime_enable(struct device *dev);
extern void __pm_runtime_disable(struct device *dev, bool check_resume);
+extern void pm_runtime_kick_last_status(struct device *dev);
extern void pm_runtime_allow(struct device *dev);
extern void pm_runtime_forbid(struct device *dev);
extern void pm_runtime_no_callbacks(struct device *dev);
@@ -288,6 +289,7 @@
static inline int pm_runtime_barrier(struct device *dev) { return 0; }
static inline void pm_runtime_enable(struct device *dev) {}
static inline void __pm_runtime_disable(struct device *dev, bool c) {}
+static inline void pm_runtime_kick_last_status(struct device *dev) {}
static inline void pm_runtime_allow(struct device *dev) {}
static inline void pm_runtime_forbid(struct device *dev) {}