From e8e298a653856b1f3a2bb7b1fe31d3faa93cc7dc Mon Sep 17 00:00:00 2001 From: Maximilian Luz Date: Fri, 4 Jun 2021 15:47:53 +0200 Subject: platform/surface: aggregator_cdev: Allow enabling of events from user-space While events can already be enabled and disabled via the generic request IOCTL, this bypasses the internal reference counting mechanism of the controller. Due to that, disabling an event will turn it off regardless of any other client having requested said event, which may break functionality of that client. To solve this, add IOCTLs wrapping the ssam_controller_event_enable() and ssam_controller_event_disable() functions, which have been previously introduced for this specific purpose. Signed-off-by: Maximilian Luz Reviewed-by: Hans de Goede Link: https://lore.kernel.org/r/20210604134755.535590-6-luzmaximilian@gmail.com Signed-off-by: Hans de Goede --- drivers/platform/surface/surface_aggregator_cdev.c | 58 ++++++++++++++++++++++ 1 file changed, 58 insertions(+) (limited to 'drivers/platform/surface') diff --git a/drivers/platform/surface/surface_aggregator_cdev.c b/drivers/platform/surface/surface_aggregator_cdev.c index dcda377896b7..7b86b36eaaa0 100644 --- a/drivers/platform/surface/surface_aggregator_cdev.c +++ b/drivers/platform/surface/surface_aggregator_cdev.c @@ -387,6 +387,58 @@ static long ssam_cdev_notif_unregister(struct ssam_cdev_client *client, return ssam_cdev_notifier_unregister(client, desc.target_category); } +static long ssam_cdev_event_enable(struct ssam_cdev_client *client, + const struct ssam_cdev_event_desc __user *d) +{ + struct ssam_cdev_event_desc desc; + struct ssam_event_registry reg; + struct ssam_event_id id; + long ret; + + /* Read descriptor from user-space. */ + ret = copy_struct_from_user(&desc, sizeof(desc), d, sizeof(*d)); + if (ret) + return ret; + + /* Translate descriptor. */ + reg.target_category = desc.reg.target_category; + reg.target_id = desc.reg.target_id; + reg.cid_enable = desc.reg.cid_enable; + reg.cid_disable = desc.reg.cid_disable; + + id.target_category = desc.id.target_category; + id.instance = desc.id.instance; + + /* Disable event. */ + return ssam_controller_event_enable(client->cdev->ctrl, reg, id, desc.flags); +} + +static long ssam_cdev_event_disable(struct ssam_cdev_client *client, + const struct ssam_cdev_event_desc __user *d) +{ + struct ssam_cdev_event_desc desc; + struct ssam_event_registry reg; + struct ssam_event_id id; + long ret; + + /* Read descriptor from user-space. */ + ret = copy_struct_from_user(&desc, sizeof(desc), d, sizeof(*d)); + if (ret) + return ret; + + /* Translate descriptor. */ + reg.target_category = desc.reg.target_category; + reg.target_id = desc.reg.target_id; + reg.cid_enable = desc.reg.cid_enable; + reg.cid_disable = desc.reg.cid_disable; + + id.target_category = desc.id.target_category; + id.instance = desc.id.instance; + + /* Disable event. */ + return ssam_controller_event_disable(client->cdev->ctrl, reg, id, desc.flags); +} + /* -- File operations. ------------------------------------------------------ */ @@ -473,6 +525,12 @@ static long __ssam_cdev_device_ioctl(struct ssam_cdev_client *client, unsigned i return ssam_cdev_notif_unregister(client, (struct ssam_cdev_notifier_desc __user *)arg); + case SSAM_CDEV_EVENT_ENABLE: + return ssam_cdev_event_enable(client, (struct ssam_cdev_event_desc __user *)arg); + + case SSAM_CDEV_EVENT_DISABLE: + return ssam_cdev_event_disable(client, (struct ssam_cdev_event_desc __user *)arg); + default: return -ENOTTY; } -- cgit v1.2.3