mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-04-13 09:59:31 +00:00
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
This commit is contained in:
parent
befe5404a0
commit
8a12b17055
3 changed files with 83 additions and 0 deletions
|
@ -257,6 +257,49 @@ void drm_privacy_screen_get_state(struct drm_privacy_screen *priv,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_privacy_screen_get_state);
|
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 ***/
|
/*** drm_privacy_screen_driver.h functions ***/
|
||||||
|
|
||||||
static ssize_t sw_state_show(struct device *dev,
|
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);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
mutex_init(&priv->lock);
|
mutex_init(&priv->lock);
|
||||||
|
BLOCKING_INIT_NOTIFIER_HEAD(&priv->notifier_head);
|
||||||
|
|
||||||
priv->dev.class = drm_class;
|
priv->dev.class = drm_class;
|
||||||
priv->dev.type = &drm_privacy_screen_type;
|
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);
|
device_unregister(&priv->dev);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_privacy_screen_unregister);
|
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);
|
||||||
|
|
|
@ -24,6 +24,11 @@ int drm_privacy_screen_set_sw_state(struct drm_privacy_screen *priv,
|
||||||
void drm_privacy_screen_get_state(struct drm_privacy_screen *priv,
|
void drm_privacy_screen_get_state(struct drm_privacy_screen *priv,
|
||||||
enum drm_privacy_screen_status *sw_state_ret,
|
enum drm_privacy_screen_status *sw_state_ret,
|
||||||
enum drm_privacy_screen_status *hw_state_ret);
|
enum drm_privacy_screen_status *hw_state_ret);
|
||||||
|
|
||||||
|
int drm_privacy_screen_register_notifier(struct drm_privacy_screen *priv,
|
||||||
|
struct notifier_block *nb);
|
||||||
|
int drm_privacy_screen_unregister_notifier(struct drm_privacy_screen *priv,
|
||||||
|
struct notifier_block *nb);
|
||||||
#else
|
#else
|
||||||
static inline struct drm_privacy_screen *drm_privacy_screen_get(struct device *dev,
|
static inline struct drm_privacy_screen *drm_privacy_screen_get(struct device *dev,
|
||||||
const char *con_id)
|
const char *con_id)
|
||||||
|
@ -45,6 +50,16 @@ static inline void drm_privacy_screen_get_state(struct drm_privacy_screen *priv,
|
||||||
*sw_state_ret = PRIVACY_SCREEN_DISABLED;
|
*sw_state_ret = PRIVACY_SCREEN_DISABLED;
|
||||||
*hw_state_ret = PRIVACY_SCREEN_DISABLED;
|
*hw_state_ret = PRIVACY_SCREEN_DISABLED;
|
||||||
}
|
}
|
||||||
|
static inline int drm_privacy_screen_register_notifier(struct drm_privacy_screen *priv,
|
||||||
|
struct notifier_block *nb)
|
||||||
|
{
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
static inline int drm_privacy_screen_unregister_notifier(struct drm_privacy_screen *priv,
|
||||||
|
struct notifier_block *nb)
|
||||||
|
{
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -54,6 +54,8 @@ struct drm_privacy_screen {
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
/** @list: privacy-screen devices list list-entry. */
|
/** @list: privacy-screen devices list list-entry. */
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
|
/** @notifier_head: privacy-screen notifier head. */
|
||||||
|
struct blocking_notifier_head notifier_head;
|
||||||
/**
|
/**
|
||||||
* @ops: &struct drm_privacy_screen_ops for this privacy-screen.
|
* @ops: &struct drm_privacy_screen_ops for this privacy-screen.
|
||||||
* This is NULL if the driver has unregistered the privacy-screen.
|
* This is NULL if the driver has unregistered the privacy-screen.
|
||||||
|
@ -77,4 +79,6 @@ struct drm_privacy_screen *drm_privacy_screen_register(
|
||||||
struct device *parent, const struct drm_privacy_screen_ops *ops);
|
struct device *parent, const struct drm_privacy_screen_ops *ops);
|
||||||
void drm_privacy_screen_unregister(struct drm_privacy_screen *priv);
|
void drm_privacy_screen_unregister(struct drm_privacy_screen *priv);
|
||||||
|
|
||||||
|
void drm_privacy_screen_call_notifier_chain(struct drm_privacy_screen *priv);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue