summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/drm_privacy_screen.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2021-10-05 22:23:16 +0200
committerHans de Goede <hdegoede@redhat.com>2021-10-14 13:12:25 +0200
commit8a12b170558aabb31cc98fda0da6a56b518cadaa (patch)
tree09f3df415d74132ec03a82e4b15c1e3962697553 /drivers/gpu/drm/drm_privacy_screen.c
parentbefe5404a00b3b1547c944738df4a9229909bdc9 (diff)
drm/privacy-screen: Add notifier support (v2)
Add support for privacy-screen consumers to register a notifier to be notified of external (e.g. done by the hw itself on a hotkey press) state changes. Changes in v2: - Drop WARN_ON(mutex_is_locked(&priv->lock)) check in drm_privacy_screen_call_notifier_chain() it may be locked by another thread, which would lead to a false-positive triggering of the check Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com> Reviewed-by: Lyude Paul <lyude@redhat.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20211005202322.700909-5-hdegoede@redhat.com
Diffstat (limited to 'drivers/gpu/drm/drm_privacy_screen.c')
-rw-r--r--drivers/gpu/drm/drm_privacy_screen.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_privacy_screen.c b/drivers/gpu/drm/drm_privacy_screen.c
index 183a6011adf0..beaf99e9120a 100644
--- a/drivers/gpu/drm/drm_privacy_screen.c
+++ b/drivers/gpu/drm/drm_privacy_screen.c
@@ -257,6 +257,49 @@ void drm_privacy_screen_get_state(struct drm_privacy_screen *priv,
}
EXPORT_SYMBOL(drm_privacy_screen_get_state);
+/**
+ * drm_privacy_screen_register_notifier - register a notifier
+ * @priv: Privacy screen to register the notifier with
+ * @nb: Notifier-block for the notifier to register
+ *
+ * Register a notifier with the privacy-screen to be notified of changes made
+ * to the privacy-screen state from outside of the privacy-screen class.
+ * E.g. the state may be changed by the hardware itself in response to a
+ * hotkey press.
+ *
+ * The notifier is called with no locks held. The new hw_state and sw_state
+ * can be retrieved using the drm_privacy_screen_get_state() function.
+ * A pointer to the drm_privacy_screen's struct is passed as the void *data
+ * argument of the notifier_block's notifier_call.
+ *
+ * The notifier will NOT be called when changes are made through
+ * drm_privacy_screen_set_sw_state(). It is only called for external changes.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int drm_privacy_screen_register_notifier(struct drm_privacy_screen *priv,
+ struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&priv->notifier_head, nb);
+}
+EXPORT_SYMBOL(drm_privacy_screen_register_notifier);
+
+/**
+ * drm_privacy_screen_unregister_notifier - unregister a notifier
+ * @priv: Privacy screen to register the notifier with
+ * @nb: Notifier-block for the notifier to register
+ *
+ * Unregister a notifier registered with drm_privacy_screen_register_notifier().
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int drm_privacy_screen_unregister_notifier(struct drm_privacy_screen *priv,
+ struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(&priv->notifier_head, nb);
+}
+EXPORT_SYMBOL(drm_privacy_screen_unregister_notifier);
+
/*** drm_privacy_screen_driver.h functions ***/
static ssize_t sw_state_show(struct device *dev,
@@ -354,6 +397,7 @@ struct drm_privacy_screen *drm_privacy_screen_register(
return ERR_PTR(-ENOMEM);
mutex_init(&priv->lock);
+ BLOCKING_INIT_NOTIFIER_HEAD(&priv->notifier_head);
priv->dev.class = drm_class;
priv->dev.type = &drm_privacy_screen_type;
@@ -401,3 +445,23 @@ void drm_privacy_screen_unregister(struct drm_privacy_screen *priv)
device_unregister(&priv->dev);
}
EXPORT_SYMBOL(drm_privacy_screen_unregister);
+
+/**
+ * drm_privacy_screen_call_notifier_chain - notify consumers of state change
+ * @priv: Privacy screen to register the notifier with
+ *
+ * A privacy-screen provider driver can call this functions upon external
+ * changes to the privacy-screen state. E.g. the state may be changed by the
+ * hardware itself in response to a hotkey press.
+ * This function must be called without holding the privacy-screen lock.
+ * the driver must update sw_state and hw_state to reflect the new state before
+ * calling this function.
+ * The expected behavior from the driver upon receiving an external state
+ * change event is: 1. Take the lock; 2. Update sw_state and hw_state;
+ * 3. Release the lock. 4. Call drm_privacy_screen_call_notifier_chain().
+ */
+void drm_privacy_screen_call_notifier_chain(struct drm_privacy_screen *priv)
+{
+ blocking_notifier_call_chain(&priv->notifier_head, 0, priv);
+}
+EXPORT_SYMBOL(drm_privacy_screen_call_notifier_chain);