From patchwork Fri Jun 4 13:47:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maximilian Luz X-Patchwork-Id: 12299807 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 16259C07E94 for ; Fri, 4 Jun 2021 13:48:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F37AE613C9 for ; Fri, 4 Jun 2021 13:48:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230418AbhFDNuT (ORCPT ); Fri, 4 Jun 2021 09:50:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38726 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230414AbhFDNuT (ORCPT ); Fri, 4 Jun 2021 09:50:19 -0400 Received: from mail-wr1-x433.google.com (mail-wr1-x433.google.com [IPv6:2a00:1450:4864:20::433]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B45DCC061766; Fri, 4 Jun 2021 06:48:20 -0700 (PDT) Received: by mail-wr1-x433.google.com with SMTP id h8so9365828wrz.8; Fri, 04 Jun 2021 06:48:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=2ETfAoIBNBhINJTqR6UlwOrmE8UtRJyCzl+e5YsJXcc=; b=Y5/sBVP4cbz/fEpeuSjzALWFMDmPwCOJA2mrvlid/bj813TELrIGMRjj9XpNeivBb2 QK39A6Py1ovExQSub5qCZ5gmUIOYgwYypLND7gfApU27fuAlHEzhuYmZTrCfX1q4QhfF 7jYnGI1PpXxizM+hAMTGEF+vMv4vm8deD7ciqEKNt2S+2mxDTyZ93iCpVzqzirEoTKv0 FIm36+DdDGoMNwa23pgs9njH+oRUEzqFECh48sCqvegW8s4RhK/+6Zu0CqaCLT11d3Ec NmszZBNjycldLPijoFtNT7Z5+cHCPSqifhZVONuyehMFoDxpudaTW3ctop2vqXrR1iVV thtQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=2ETfAoIBNBhINJTqR6UlwOrmE8UtRJyCzl+e5YsJXcc=; b=HMhoxyj65enoLSyDEfV4j7TrQurI96fM82hYWmASmxkHTM0m3UXd7Sh/hoTHl/F4Hk JibXWlQ4IecOkvc7utsFNdMp0uxhy8iQkaPi3eKGi6QNdM8z8XrYfpCztpP25Jaeh/a7 Pi4W2+NSqEdDlyBpP/NUOQnaWyOSTeOyh16Valo26QtNtEi1++wCIJQWyHViVA4lsYZk A1PC3a4nhnmGpJATluWRjIYAIP5MBXSusY6d6BoIBnQKRcw5f7lxe8HH0VUu6c4N8SdE z+0TPEbFnhKAqXwNqLSYJrAj5Bq0yTWyt0e3y0trkZaTfzN5VHgORkdZMGEuQF/JQg5R YMZw== X-Gm-Message-State: AOAM533PwvP3fOeJrMWmwk4SegU8rKdmp/BhfIWcV9cg6isYlNy322Zr jnoqqMSi7jSb9x173ym9DUg= X-Google-Smtp-Source: ABdhPJzKDX8t3tlny7tVWmgjExSH7DIyCceDeOv5GRO6mA5GkblNzyi8SJarKHBzbvqXoWr6qY7t7Q== X-Received: by 2002:a5d:4848:: with SMTP id n8mr4195817wrs.70.1622814499242; Fri, 04 Jun 2021 06:48:19 -0700 (PDT) Received: from xws.localdomain (pd9e5aba0.dip0.t-ipconnect.de. [217.229.171.160]) by smtp.gmail.com with ESMTPSA id u16sm7403167wru.56.2021.06.04.06.48.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Jun 2021 06:48:18 -0700 (PDT) From: Maximilian Luz To: Hans de Goede Cc: Maximilian Luz , Mark Gross , platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 1/7] platform/surface: aggregator: Allow registering notifiers without enabling events Date: Fri, 4 Jun 2021 15:47:49 +0200 Message-Id: <20210604134755.535590-2-luzmaximilian@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210604134755.535590-1-luzmaximilian@gmail.com> References: <20210604134755.535590-1-luzmaximilian@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org Currently, each SSAM event notifier is directly tied to one group of events. This makes sense as registering a notifier will automatically take care of enabling the corresponding event group and normally drivers only need notifications for a very limited number of events, associated with different callbacks for each group. However, there are rare cases, especially for debugging, when we want to get notifications for a whole event target category instead of just a single group of events in that category. Registering multiple notifiers, i.e. one per group, may be infeasible due to two issues: a) we might not know every event enable/disable specification as some events are auto-enabled by the EC and b) forwarding this to the same callback will lead to duplicate events as we might not know the full event specification to perform the appropriate filtering. This commit introduces observer-notifiers, which are notifiers that are not tied to a specific event group and do not attempt to manage any events. In other words, they can be registered without enabling any event group or incrementing the corresponding reference count and just act as silent observers, listening to all currently/previously enabled events based on their match-specification. Essentially, this allows us to register one single notifier for a full event target category, meaning that we can process all events of that target category in a single callback without duplication. Specifically, this will be used in the cdev debug interface to forward events to user-space via a device file from which the events can be read. Signed-off-by: Maximilian Luz Reviewed-by: Hans de Goede --- Changes in v2: - None --- .../platform/surface/aggregator/controller.c | 69 +++++++++++-------- include/linux/surface_aggregator/controller.h | 17 +++++ 2 files changed, 58 insertions(+), 28 deletions(-) diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c index a06964aa96e7..cd3a6b77f48d 100644 --- a/drivers/platform/surface/aggregator/controller.c +++ b/drivers/platform/surface/aggregator/controller.c @@ -2127,9 +2127,15 @@ int ssam_ctrl_notif_d0_entry(struct ssam_controller *ctrl) * @ctrl: The controller to register the notifier on. * @n: The event notifier to register. * - * Register an event notifier and increment the usage counter of the - * associated SAM event. If the event was previously not enabled, it will be - * enabled during this call. + * Register an event notifier. Increment the usage counter of the associated + * SAM event if the notifier is not marked as an observer. If the event is not + * marked as an observer and is currently not enabled, it will be enabled + * during this call. If the notifier is marked as an observer, no attempt will + * be made at enabling any event and no reference count will be modified. + * + * Notifiers marked as observers do not need to be associated with one specific + * event, i.e. as long as no event matching is performed, only the event target + * category needs to be set. * * Return: Returns zero on success, %-ENOSPC if there have already been * %INT_MAX notifiers for the event ID/type associated with the notifier block @@ -2138,11 +2144,10 @@ int ssam_ctrl_notif_d0_entry(struct ssam_controller *ctrl) * for the specific associated event, returns the status of the event-enable * EC-command. */ -int ssam_notifier_register(struct ssam_controller *ctrl, - struct ssam_event_notifier *n) +int ssam_notifier_register(struct ssam_controller *ctrl, struct ssam_event_notifier *n) { u16 rqid = ssh_tc_to_rqid(n->event.id.target_category); - struct ssam_nf_refcount_entry *entry; + struct ssam_nf_refcount_entry *entry = NULL; struct ssam_nf_head *nf_head; struct ssam_nf *nf; int status; @@ -2155,29 +2160,32 @@ int ssam_notifier_register(struct ssam_controller *ctrl, mutex_lock(&nf->lock); - entry = ssam_nf_refcount_inc(nf, n->event.reg, n->event.id); - if (IS_ERR(entry)) { - mutex_unlock(&nf->lock); - return PTR_ERR(entry); - } + if (!(n->flags & SSAM_EVENT_NOTIFIER_OBSERVER)) { + entry = ssam_nf_refcount_inc(nf, n->event.reg, n->event.id); + if (IS_ERR(entry)) { + mutex_unlock(&nf->lock); + return PTR_ERR(entry); + } - ssam_dbg(ctrl, "enabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n", - n->event.reg.target_category, n->event.id.target_category, - n->event.id.instance, entry->refcount); + ssam_dbg(ctrl, "enabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n", + n->event.reg.target_category, n->event.id.target_category, + n->event.id.instance, entry->refcount); + } status = ssam_nfblk_insert(nf_head, &n->base); if (status) { - entry = ssam_nf_refcount_dec(nf, n->event.reg, n->event.id); - if (entry->refcount == 0) - kfree(entry); + if (entry) { + entry = ssam_nf_refcount_dec(nf, n->event.reg, n->event.id); + if (entry->refcount == 0) + kfree(entry); + } mutex_unlock(&nf->lock); return status; } - if (entry->refcount == 1) { - status = ssam_ssh_event_enable(ctrl, n->event.reg, n->event.id, - n->event.flags); + if (entry && entry->refcount == 1) { + status = ssam_ssh_event_enable(ctrl, n->event.reg, n->event.id, n->event.flags); if (status) { ssam_nfblk_remove(&n->base); kfree(ssam_nf_refcount_dec(nf, n->event.reg, n->event.id)); @@ -2188,7 +2196,7 @@ int ssam_notifier_register(struct ssam_controller *ctrl, entry->flags = n->event.flags; - } else if (entry->flags != n->event.flags) { + } else if (entry && entry->flags != n->event.flags) { ssam_warn(ctrl, "inconsistent flags when enabling event: got %#04x, expected %#04x (reg: %#04x, tc: %#04x, iid: %#04x)\n", n->event.flags, entry->flags, n->event.reg.target_category, @@ -2205,17 +2213,16 @@ EXPORT_SYMBOL_GPL(ssam_notifier_register); * @ctrl: The controller the notifier has been registered on. * @n: The event notifier to unregister. * - * Unregister an event notifier and decrement the usage counter of the - * associated SAM event. If the usage counter reaches zero, the event will be - * disabled. + * Unregister an event notifier. Decrement the usage counter of the associated + * SAM event if the notifier is not marked as an observer. If the usage counter + * reaches zero, the event will be disabled. * * Return: Returns zero on success, %-ENOENT if the given notifier block has * not been registered on the controller. If the given notifier block was the * last one associated with its specific event, returns the status of the * event-disable EC-command. */ -int ssam_notifier_unregister(struct ssam_controller *ctrl, - struct ssam_event_notifier *n) +int ssam_notifier_unregister(struct ssam_controller *ctrl, struct ssam_event_notifier *n) { u16 rqid = ssh_tc_to_rqid(n->event.id.target_category); struct ssam_nf_refcount_entry *entry; @@ -2236,6 +2243,13 @@ int ssam_notifier_unregister(struct ssam_controller *ctrl, return -ENOENT; } + /* + * If this is an observer notifier, do not attempt to disable the + * event, just remove it. + */ + if (n->flags & SSAM_EVENT_NOTIFIER_OBSERVER) + goto remove; + entry = ssam_nf_refcount_dec(nf, n->event.reg, n->event.id); if (WARN_ON(!entry)) { /* @@ -2260,8 +2274,7 @@ int ssam_notifier_unregister(struct ssam_controller *ctrl, } if (entry->refcount == 0) { - status = ssam_ssh_event_disable(ctrl, n->event.reg, n->event.id, - n->event.flags); + status = ssam_ssh_event_disable(ctrl, n->event.reg, n->event.id, n->event.flags); kfree(entry); } diff --git a/include/linux/surface_aggregator/controller.h b/include/linux/surface_aggregator/controller.h index 0806796eabcb..cf4bb48a850e 100644 --- a/include/linux/surface_aggregator/controller.h +++ b/include/linux/surface_aggregator/controller.h @@ -795,6 +795,20 @@ enum ssam_event_mask { #define SSAM_EVENT_REGISTRY_REG \ SSAM_EVENT_REGISTRY(SSAM_SSH_TC_REG, 0x02, 0x01, 0x02) +/** + * enum ssam_event_notifier_flags - Flags for event notifiers. + * @SSAM_EVENT_NOTIFIER_OBSERVER: + * The corresponding notifier acts as observer. Registering a notifier + * with this flag set will not attempt to enable any event. Equally, + * unregistering will not attempt to disable any event. Note that a + * notifier with this flag may not even correspond to a certain event at + * all, only to a specific event target category. Event matching will not + * be influenced by this flag. + */ +enum ssam_event_notifier_flags { + SSAM_EVENT_NOTIFIER_OBSERVER = BIT(0), +}; + /** * struct ssam_event_notifier - Notifier block for SSAM events. * @base: The base notifier block with callback function and priority. @@ -803,6 +817,7 @@ enum ssam_event_mask { * @event.id: ID specifying the event. * @event.mask: Flags determining how events are matched to the notifier. * @event.flags: Flags used for enabling the event. + * @flags: Notifier flags (see &enum ssam_event_notifier_flags). */ struct ssam_event_notifier { struct ssam_notifier_block base; @@ -813,6 +828,8 @@ struct ssam_event_notifier { enum ssam_event_mask mask; u8 flags; } event; + + unsigned long flags; }; int ssam_notifier_register(struct ssam_controller *ctrl, From patchwork Fri Jun 4 13:47:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maximilian Luz X-Patchwork-Id: 12299809 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6AE6EC4708F for ; Fri, 4 Jun 2021 13:48:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 50E01613FA for ; Fri, 4 Jun 2021 13:48:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230435AbhFDNuT (ORCPT ); Fri, 4 Jun 2021 09:50:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38732 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230004AbhFDNuT (ORCPT ); Fri, 4 Jun 2021 09:50:19 -0400 Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C1744C061767; Fri, 4 Jun 2021 06:48:21 -0700 (PDT) Received: by mail-wr1-x434.google.com with SMTP id h8so9365881wrz.8; Fri, 04 Jun 2021 06:48:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=KfHKxaz7aWTGDT2RfXcawOt0jx58xz6euWl0ucInBZM=; b=oLQjHEFGaBGigH28CcW5TC+n4EsStcYe/XLTm4DJP6tLx6B3hiQtf4889N1IQpKvy+ k8B7XJFth7vVU3BLyRGAIyGCcF/o4QQvrbbRSmsLDYdPV9T+/fot8VG2NghTrYGlEYzh nirzCHuOHYvLtktbqIsjOlVM8S3n1mJeggPC8bgZLZFxQ0iJ8VfkBtt71x3Mh6mdsah8 lbUcj4qe7tfXOceeynGudvuhnzcLZM5H8BCHYCRqJN+8T1ZuPFXX72+lnwGY00ogp9qO ZD2uF9tK/U0lc4IwJOrfZVzd5EdeIMPFZ8R2bu7mcNakpff/nmnYyy64h8bf0m14hJ9E YBWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=KfHKxaz7aWTGDT2RfXcawOt0jx58xz6euWl0ucInBZM=; b=YgxObRL+Wj+1Y/Ho+UCmczN7W8jhfyvx+5XMojgdJRrH0fxmRzTFUQ+iE6+dltNlsu wscTc/YwDwDDE68Bd07V+ebNvDa3YjXtV5mHglKw4kbz6PlJYDi8a+hXxZaMBkoHzE9K w98ggCne5i7+mqiyqF/+yb8GmdcMrOiby4MDAsBuLJazykkfc30nWa1dvYHRGTzlZObf IQupR0adASsqQuFWf8u7PsNqQQ8ehusaVt1i6AHTQLwWpTwGzKebYlg5PmrjVBM3URdn g/iC0L/9VXUaVbPguMHDl+6/4rDBd88LFchp/3KRakdLUN+NL8Ncl2NaUAh0NUp2rQjU NEGA== X-Gm-Message-State: AOAM531B1GQYo4AFZqR3sXye4ZfQCI1xTecIhx1CqWJKoq/fGBjxLABw l6+WOGQxvGPGSvEciTbP/9Q= X-Google-Smtp-Source: ABdhPJxQwfGwS3xNf6dYFl+0qX5Kn1MWYofgxTAvHqoBv57B9TBKYWvDE41YwNiaR1L8KYUUibTNfQ== X-Received: by 2002:a05:6000:1849:: with SMTP id c9mr4153989wri.140.1622814500329; Fri, 04 Jun 2021 06:48:20 -0700 (PDT) Received: from xws.localdomain (pd9e5aba0.dip0.t-ipconnect.de. [217.229.171.160]) by smtp.gmail.com with ESMTPSA id u16sm7403167wru.56.2021.06.04.06.48.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Jun 2021 06:48:19 -0700 (PDT) From: Maximilian Luz To: Hans de Goede Cc: Maximilian Luz , Mark Gross , platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 2/7] platform/surface: aggregator: Allow enabling of events without notifiers Date: Fri, 4 Jun 2021 15:47:50 +0200 Message-Id: <20210604134755.535590-3-luzmaximilian@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210604134755.535590-1-luzmaximilian@gmail.com> References: <20210604134755.535590-1-luzmaximilian@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org We can already enable and disable SAM events via one of two ways: either via a (non-observer) notifier tied to a specific event group, or a generic event enable/disable request. In some instances, however, neither method may be desirable. The first method will tie the event enable request to a specific notifier, however, when we want to receive notifications for multiple event groups of the same target category and forward this to the same notifier callback, we may receive duplicate events, i.e. one event per registered notifier. The second method will bypass the internal reference counting mechanism, meaning that a disable request will disable the event regardless of any other client driver using it, which may break the functionality of that driver. To address this problem, add new functions that allow enabling and disabling of events via the event reference counting mechanism built into the controller, without needing to register a notifier. This can then be used in combination with observer notifiers to process multiple events of the same target category without duplication in the same callback function. Signed-off-by: Maximilian Luz Reported-by: kernel test robot --- Changes in v2: - Remove unused variable - Avoid code duplication --- .../platform/surface/aggregator/controller.c | 293 +++++++++++++++--- include/linux/surface_aggregator/controller.h | 8 + 2 files changed, 253 insertions(+), 48 deletions(-) diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c index cd3a6b77f48d..c673aa8309c8 100644 --- a/drivers/platform/surface/aggregator/controller.c +++ b/drivers/platform/surface/aggregator/controller.c @@ -407,6 +407,31 @@ ssam_nf_refcount_dec(struct ssam_nf *nf, struct ssam_event_registry reg, return NULL; } +/** + * ssam_nf_refcount_dec_free() - Decrement reference-/activation-count of the + * given event and free its entry if the reference count reaches zero. + * @nf: The notifier system reference. + * @reg: The registry used to enable/disable the event. + * @id: The event ID. + * + * Decrements the reference-/activation-count of the specified event, freeing + * its entry if it reaches zero. + * + * Note: ``nf->lock`` must be held when calling this function. + */ +static void ssam_nf_refcount_dec_free(struct ssam_nf *nf, + struct ssam_event_registry reg, + struct ssam_event_id id) +{ + struct ssam_nf_refcount_entry *entry; + + lockdep_assert_held(&nf->lock); + + entry = ssam_nf_refcount_dec(nf, reg, id); + if (entry && entry->refcount == 0) + kfree(entry); +} + /** * ssam_nf_refcount_empty() - Test if the notification system has any * enabled/active events. @@ -2122,6 +2147,109 @@ int ssam_ctrl_notif_d0_entry(struct ssam_controller *ctrl) /* -- Top-level event registry interface. ----------------------------------- */ +/** + * ssam_nf_refcount_enable() - Enable event for reference count entry if it has + * not already been enabled. + * @ctrl: The controller to enable the event on. + * @entry: The reference count entry for the event to be enabled. + * @flags: The flags used for enabling the event on the EC. + * + * Enable the event associated with the given reference count entry if the + * reference count equals one, i.e. the event has not previously been enabled. + * If the event has already been enabled (i.e. reference count not equal to + * one), check that the flags used for enabling match and warn about this if + * they do not. + * + * This does not modify the reference count itself, which is done with + * ssam_nf_refcount_inc() / ssam_nf_refcount_dec(). + * + * Note: ``nf->lock`` must be held when calling this function. + * + * Return: Returns zero on success. If the event is enabled by this call, + * returns the status of the event-enable EC command. + */ +static int ssam_nf_refcount_enable(struct ssam_controller *ctrl, + struct ssam_nf_refcount_entry *entry, u8 flags) +{ + const struct ssam_event_registry reg = entry->key.reg; + const struct ssam_event_id id = entry->key.id; + struct ssam_nf *nf = &ctrl->cplt.event.notif; + int status; + + lockdep_assert_held(&nf->lock); + + ssam_dbg(ctrl, "enabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n", + reg.target_category, id.target_category, id.instance, entry->refcount); + + if (entry->refcount == 1) { + status = ssam_ssh_event_enable(ctrl, reg, id, flags); + if (status) + return status; + + entry->flags = flags; + + } else if (entry->flags != flags) { + ssam_warn(ctrl, + "inconsistent flags when enabling event: got %#04x, expected %#04x (reg: %#04x, tc: %#04x, iid: %#04x)\n", + flags, entry->flags, reg.target_category, id.target_category, + id.instance); + } + + return 0; +} + +/** + * ssam_nf_refcount_enable() - Disable event for reference count entry if it is + * no longer in use and free the corresponding entry. + * @ctrl: The controller to disable the event on. + * @entry: The reference count entry for the event to be disabled. + * @flags: The flags used for enabling the event on the EC. + * + * If the reference count equals zero, i.e. the event is no longer requested by + * any client, the event will be disabled and the corresponding reference count + * entry freed. The reference count entry must not be used any more after a + * call to this function. + * + * Also checks if the flags used for disabling the event match the flags used + * for enabling the event and warns if they do not (regardless of reference + * count). + * + * This does not modify the reference count itself, which is done with + * ssam_nf_refcount_inc() / ssam_nf_refcount_dec(). + * + * Note: ``nf->lock`` must be held when calling this function. + * + * Return: Returns zero on success. If the event is disabled by this call, + * returns the status of the event-enable EC command. + */ +static int ssam_nf_refcount_disable_free(struct ssam_controller *ctrl, + struct ssam_nf_refcount_entry *entry, u8 flags) +{ + const struct ssam_event_registry reg = entry->key.reg; + const struct ssam_event_id id = entry->key.id; + struct ssam_nf *nf = &ctrl->cplt.event.notif; + int status; + + lockdep_assert_held(&nf->lock); + + ssam_dbg(ctrl, "disabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n", + reg.target_category, id.target_category, id.instance, entry->refcount); + + if (entry->flags != flags) { + ssam_warn(ctrl, + "inconsistent flags when disabling event: got %#04x, expected %#04x (reg: %#04x, tc: %#04x, iid: %#04x)\n", + flags, entry->flags, reg.target_category, id.target_category, + id.instance); + } + + if (entry->refcount == 0) { + status = ssam_ssh_event_disable(ctrl, reg, id, flags); + kfree(entry); + } + + return status; +} + /** * ssam_notifier_register() - Register an event notifier. * @ctrl: The controller to register the notifier on. @@ -2166,41 +2294,26 @@ int ssam_notifier_register(struct ssam_controller *ctrl, struct ssam_event_notif mutex_unlock(&nf->lock); return PTR_ERR(entry); } - - ssam_dbg(ctrl, "enabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n", - n->event.reg.target_category, n->event.id.target_category, - n->event.id.instance, entry->refcount); } status = ssam_nfblk_insert(nf_head, &n->base); if (status) { - if (entry) { - entry = ssam_nf_refcount_dec(nf, n->event.reg, n->event.id); - if (entry->refcount == 0) - kfree(entry); - } + if (entry) + ssam_nf_refcount_dec_free(nf, n->event.reg, n->event.id); mutex_unlock(&nf->lock); return status; } - if (entry && entry->refcount == 1) { - status = ssam_ssh_event_enable(ctrl, n->event.reg, n->event.id, n->event.flags); + if (entry) { + status = ssam_nf_refcount_enable(ctrl, entry, n->event.flags); if (status) { ssam_nfblk_remove(&n->base); - kfree(ssam_nf_refcount_dec(nf, n->event.reg, n->event.id)); + ssam_nf_refcount_dec_free(nf, n->event.reg, n->event.id); mutex_unlock(&nf->lock); synchronize_srcu(&nf_head->srcu); return status; } - - entry->flags = n->event.flags; - - } else if (entry && entry->flags != n->event.flags) { - ssam_warn(ctrl, - "inconsistent flags when enabling event: got %#04x, expected %#04x (reg: %#04x, tc: %#04x, iid: %#04x)\n", - n->event.flags, entry->flags, n->event.reg.target_category, - n->event.id.target_category, n->event.id.instance); } mutex_unlock(&nf->lock); @@ -2247,35 +2360,20 @@ int ssam_notifier_unregister(struct ssam_controller *ctrl, struct ssam_event_not * If this is an observer notifier, do not attempt to disable the * event, just remove it. */ - if (n->flags & SSAM_EVENT_NOTIFIER_OBSERVER) - goto remove; - - entry = ssam_nf_refcount_dec(nf, n->event.reg, n->event.id); - if (WARN_ON(!entry)) { - /* - * If this does not return an entry, there's a logic error - * somewhere: The notifier block is registered, but the event - * refcount entry is not there. Remove the notifier block - * anyways. - */ - status = -ENOENT; - goto remove; - } - - ssam_dbg(ctrl, "disabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n", - n->event.reg.target_category, n->event.id.target_category, - n->event.id.instance, entry->refcount); - - if (entry->flags != n->event.flags) { - ssam_warn(ctrl, - "inconsistent flags when disabling event: got %#04x, expected %#04x (reg: %#04x, tc: %#04x, iid: %#04x)\n", - n->event.flags, entry->flags, n->event.reg.target_category, - n->event.id.target_category, n->event.id.instance); - } + if (!(n->flags & SSAM_EVENT_NOTIFIER_OBSERVER)) { + entry = ssam_nf_refcount_dec(nf, n->event.reg, n->event.id); + if (WARN_ON(!entry)) { + /* + * If this does not return an entry, there's a logic + * error somewhere: The notifier block is registered, + * but the event refcount entry is not there. Remove + * the notifier block anyways. + */ + status = -ENOENT; + goto remove; + } - if (entry->refcount == 0) { - status = ssam_ssh_event_disable(ctrl, n->event.reg, n->event.id, n->event.flags); - kfree(entry); + status = ssam_nf_refcount_disable_free(ctrl, entry, n->event.flags); } remove: @@ -2287,6 +2385,105 @@ int ssam_notifier_unregister(struct ssam_controller *ctrl, struct ssam_event_not } EXPORT_SYMBOL_GPL(ssam_notifier_unregister); +/** + * ssam_controller_event_enable() - Enable the specified event. + * @ctrl: The controller to enable the event for. + * @reg: The event registry to use for enabling the event. + * @id: The event ID specifying the event to be enabled. + * @flags: The SAM event flags used for enabling the event. + * + * Increment the event reference count of the specified event. If the event has + * not been enabled previously, it will be enabled by this call. + * + * Note: In general, ssam_notifier_register() with a non-observer notifier + * should be preferred for enabling/disabling events, as this will guarantee + * proper ordering and event forwarding in case of errors during event + * enabling/disabling. + * + * Return: Returns zero on success, %-ENOSPC if the reference count for the + * specified event has reached its maximum, %-ENOMEM if the corresponding event + * entry could not be allocated. If this is the first time that this event has + * been enabled (i.e. the reference count was incremented from zero to one by + * this call), returns the status of the event-enable EC-command. + */ +int ssam_controller_event_enable(struct ssam_controller *ctrl, + struct ssam_event_registry reg, + struct ssam_event_id id, u8 flags) +{ + u16 rqid = ssh_tc_to_rqid(id.target_category); + struct ssam_nf *nf = &ctrl->cplt.event.notif; + struct ssam_nf_refcount_entry *entry; + int status; + + if (!ssh_rqid_is_event(rqid)) + return -EINVAL; + + mutex_lock(&nf->lock); + + entry = ssam_nf_refcount_inc(nf, reg, id); + if (IS_ERR(entry)) { + mutex_unlock(&nf->lock); + return PTR_ERR(entry); + } + + status = ssam_nf_refcount_enable(ctrl, entry, flags); + if (status) { + ssam_nf_refcount_dec_free(nf, reg, id); + mutex_unlock(&nf->lock); + return status; + } + + mutex_unlock(&nf->lock); + return 0; +} +EXPORT_SYMBOL_GPL(ssam_controller_event_enable); + +/** + * ssam_controller_event_disable() - Disable the specified event. + * @ctrl: The controller to disable the event for. + * @reg: The event registry to use for disabling the event. + * @id: The event ID specifying the event to be disabled. + * @flags: The flags used when enabling the event. + * + * Decrement the reference count of the specified event. If the reference count + * reaches zero, the event will be disabled. + * + * Note: In general, ssam_notifier_register()/ssam_notifier_unregister() with a + * non-observer notifier should be preferred for enabling/disabling events, as + * this will guarantee proper ordering and event forwarding in case of errors + * during event enabling/disabling. + * + * Return: Returns zero on success, %-ENOENT if the given event has not been + * enabled on the controller. If the reference count of the event reaches zero + * during this call, returns the status of the event-disable EC-command. + */ +int ssam_controller_event_disable(struct ssam_controller *ctrl, + struct ssam_event_registry reg, + struct ssam_event_id id, u8 flags) +{ + u16 rqid = ssh_tc_to_rqid(id.target_category); + struct ssam_nf *nf = &ctrl->cplt.event.notif; + struct ssam_nf_refcount_entry *entry; + int status = 0; + + if (!ssh_rqid_is_event(rqid)) + return -EINVAL; + + mutex_lock(&nf->lock); + + entry = ssam_nf_refcount_dec(nf, reg, id); + if (!entry) { + mutex_unlock(&nf->lock); + return -ENOENT; + } + + status = ssam_nf_refcount_disable_free(ctrl, entry, flags); + + mutex_unlock(&nf->lock); + return status; +} +EXPORT_SYMBOL_GPL(ssam_controller_event_disable); + /** * ssam_notifier_disable_registered() - Disable events for all registered * notifiers. diff --git a/include/linux/surface_aggregator/controller.h b/include/linux/surface_aggregator/controller.h index cf4bb48a850e..7965bdc669c5 100644 --- a/include/linux/surface_aggregator/controller.h +++ b/include/linux/surface_aggregator/controller.h @@ -838,4 +838,12 @@ int ssam_notifier_register(struct ssam_controller *ctrl, int ssam_notifier_unregister(struct ssam_controller *ctrl, struct ssam_event_notifier *n); +int ssam_controller_event_enable(struct ssam_controller *ctrl, + struct ssam_event_registry reg, + struct ssam_event_id id, u8 flags); + +int ssam_controller_event_disable(struct ssam_controller *ctrl, + struct ssam_event_registry reg, + struct ssam_event_id id, u8 flags); + #endif /* _LINUX_SURFACE_AGGREGATOR_CONTROLLER_H */ From patchwork Fri Jun 4 13:47:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maximilian Luz X-Patchwork-Id: 12299811 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B5558C4708F for ; Fri, 4 Jun 2021 13:48:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A1766613FA for ; Fri, 4 Jun 2021 13:48:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231160AbhFDNu0 (ORCPT ); Fri, 4 Jun 2021 09:50:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38736 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230004AbhFDNuZ (ORCPT ); Fri, 4 Jun 2021 09:50:25 -0400 Received: from mail-wm1-x331.google.com (mail-wm1-x331.google.com [IPv6:2a00:1450:4864:20::331]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id ABF1CC061768; Fri, 4 Jun 2021 06:48:22 -0700 (PDT) Received: by mail-wm1-x331.google.com with SMTP id t4-20020a1c77040000b029019d22d84ebdso7946723wmi.3; Fri, 04 Jun 2021 06:48:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=3A9nKUhXlAsdzVYpKKxMoJNv7x9Ic1OvtPp5GTZtTZs=; b=mrOIzFFmzNq7FMb0jxVLbPxGs4E7IrQQmzeOpxE81vnXEd1ijt96WrZ2szBs0GXUJz pkpsH7lOmgcuHf9z2Eo9UBnjpRT7Lg6eQIpGyXxbcM+Itc3pPppYAorrCe6ComhBf0sb ogMEZrEvO7K8BbRV1qz0u9E4+Ub82EffMH+Hp3v3nKYF+psifucZwkQNDNvgMCbDcKKH Jf6N0nyCqC6ZOq/8UTHK6bR9JNSZs5HrkORCe/2BsOl5y+CbdIKrqGQvQwIePn77pYQd JJhcUqg056mn8FbISNpc2ufeUixalc/TC2ZZ/LGpP/89GpeB9UbhKzh3fY23frkd+3c5 5Ubg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=3A9nKUhXlAsdzVYpKKxMoJNv7x9Ic1OvtPp5GTZtTZs=; b=KZOOaGW067jbheUVsSDLOJfoJzqNYDODlnrhDDURK68qLttziVVlkKJhJBAan7oeU1 DFhrYCZYKNtnAa/kgXAjvTJxRGlDwyfXgutT/0FkshVfmN4CU6SEZm/jfFki7EpHPxq9 4mSwRsZ3XQa1YgCioXLFthQsCWLJlUmHAy9gSRmpEMT3P2pmwyK40TH8B+SHi1eKZfSO K/Fuo/JF7FxHrbZeBqSH6BVoAvkQhAL6nqCkyE+afWoq/saAQtnLh4UnJl7m0kaC3/OM GYm7zWw8lIlM9nVD3NVPuHg/qJ+rC9jpUnOW2hFRUsIRY8YP36o0poO6eLZHyFV/4Zij XcHQ== X-Gm-Message-State: AOAM533aUGhRS+SVx1CIqG+A5RHiyHJ3LuVrWapy2kakxpO+u3BlWYBY JXEDWrBUrOZRWyb7t0I5lns= X-Google-Smtp-Source: ABdhPJz0KF6jEq9va9+BKn/LaYpliICcPlL5KovstNd5GzbAb5ZBdzIjkYVOjPrbsgzeaVBC2NYt5A== X-Received: by 2002:a1c:bad6:: with SMTP id k205mr3904228wmf.171.1622814501257; Fri, 04 Jun 2021 06:48:21 -0700 (PDT) Received: from xws.localdomain (pd9e5aba0.dip0.t-ipconnect.de. [217.229.171.160]) by smtp.gmail.com with ESMTPSA id u16sm7403167wru.56.2021.06.04.06.48.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Jun 2021 06:48:20 -0700 (PDT) From: Maximilian Luz To: Hans de Goede Cc: Maximilian Luz , Mark Gross , platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 3/7] platform/surface: aggregator: Update copyright Date: Fri, 4 Jun 2021 15:47:51 +0200 Message-Id: <20210604134755.535590-4-luzmaximilian@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210604134755.535590-1-luzmaximilian@gmail.com> References: <20210604134755.535590-1-luzmaximilian@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org It's 2021, update the copyright accordingly. Signed-off-by: Maximilian Luz Reviewed-by: Hans de Goede --- Changes in v2: - None --- drivers/platform/surface/aggregator/Kconfig | 2 +- drivers/platform/surface/aggregator/Makefile | 2 +- drivers/platform/surface/aggregator/bus.c | 2 +- drivers/platform/surface/aggregator/bus.h | 2 +- drivers/platform/surface/aggregator/controller.c | 2 +- drivers/platform/surface/aggregator/controller.h | 2 +- drivers/platform/surface/aggregator/core.c | 2 +- drivers/platform/surface/aggregator/ssh_msgb.h | 2 +- drivers/platform/surface/aggregator/ssh_packet_layer.c | 2 +- drivers/platform/surface/aggregator/ssh_packet_layer.h | 2 +- drivers/platform/surface/aggregator/ssh_parser.c | 2 +- drivers/platform/surface/aggregator/ssh_parser.h | 2 +- drivers/platform/surface/aggregator/ssh_request_layer.c | 2 +- drivers/platform/surface/aggregator/ssh_request_layer.h | 2 +- drivers/platform/surface/aggregator/trace.h | 2 +- include/linux/surface_aggregator/controller.h | 2 +- include/linux/surface_aggregator/device.h | 2 +- include/linux/surface_aggregator/serial_hub.h | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/platform/surface/aggregator/Kconfig b/drivers/platform/surface/aggregator/Kconfig index 3aaeea9f0433..fd6dc452f3e8 100644 --- a/drivers/platform/surface/aggregator/Kconfig +++ b/drivers/platform/surface/aggregator/Kconfig @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0+ -# Copyright (C) 2019-2020 Maximilian Luz +# Copyright (C) 2019-2021 Maximilian Luz menuconfig SURFACE_AGGREGATOR tristate "Microsoft Surface System Aggregator Module Subsystem and Drivers" diff --git a/drivers/platform/surface/aggregator/Makefile b/drivers/platform/surface/aggregator/Makefile index c112e2c7112b..c8498c41e758 100644 --- a/drivers/platform/surface/aggregator/Makefile +++ b/drivers/platform/surface/aggregator/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0+ -# Copyright (C) 2019-2020 Maximilian Luz +# Copyright (C) 2019-2021 Maximilian Luz # For include/trace/define_trace.h to include trace.h CFLAGS_core.o = -I$(src) diff --git a/drivers/platform/surface/aggregator/bus.c b/drivers/platform/surface/aggregator/bus.c index a9b660af0917..0169677c243e 100644 --- a/drivers/platform/surface/aggregator/bus.c +++ b/drivers/platform/surface/aggregator/bus.c @@ -2,7 +2,7 @@ /* * Surface System Aggregator Module bus and device integration. * - * Copyright (C) 2019-2020 Maximilian Luz + * Copyright (C) 2019-2021 Maximilian Luz */ #include diff --git a/drivers/platform/surface/aggregator/bus.h b/drivers/platform/surface/aggregator/bus.h index 7712baaed6a5..ed032c2cbdb2 100644 --- a/drivers/platform/surface/aggregator/bus.h +++ b/drivers/platform/surface/aggregator/bus.h @@ -2,7 +2,7 @@ /* * Surface System Aggregator Module bus and device integration. * - * Copyright (C) 2019-2020 Maximilian Luz + * Copyright (C) 2019-2021 Maximilian Luz */ #ifndef _SURFACE_AGGREGATOR_BUS_H diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c index c673aa8309c8..14cd7b31ccc1 100644 --- a/drivers/platform/surface/aggregator/controller.c +++ b/drivers/platform/surface/aggregator/controller.c @@ -2,7 +2,7 @@ /* * Main SSAM/SSH controller structure and functionality. * - * Copyright (C) 2019-2020 Maximilian Luz + * Copyright (C) 2019-2021 Maximilian Luz */ #include diff --git a/drivers/platform/surface/aggregator/controller.h b/drivers/platform/surface/aggregator/controller.h index 8297d34e7489..a0963c3562ff 100644 --- a/drivers/platform/surface/aggregator/controller.h +++ b/drivers/platform/surface/aggregator/controller.h @@ -2,7 +2,7 @@ /* * Main SSAM/SSH controller structure and functionality. * - * Copyright (C) 2019-2020 Maximilian Luz + * Copyright (C) 2019-2021 Maximilian Luz */ #ifndef _SURFACE_AGGREGATOR_CONTROLLER_H diff --git a/drivers/platform/surface/aggregator/core.c b/drivers/platform/surface/aggregator/core.c index 8dc2c267bcd6..5d780e55f4a1 100644 --- a/drivers/platform/surface/aggregator/core.c +++ b/drivers/platform/surface/aggregator/core.c @@ -7,7 +7,7 @@ * Handles communication via requests as well as enabling, disabling, and * relaying of events. * - * Copyright (C) 2019-2020 Maximilian Luz + * Copyright (C) 2019-2021 Maximilian Luz */ #include diff --git a/drivers/platform/surface/aggregator/ssh_msgb.h b/drivers/platform/surface/aggregator/ssh_msgb.h index 1221f642dda1..e562958ffdf0 100644 --- a/drivers/platform/surface/aggregator/ssh_msgb.h +++ b/drivers/platform/surface/aggregator/ssh_msgb.h @@ -2,7 +2,7 @@ /* * SSH message builder functions. * - * Copyright (C) 2019-2020 Maximilian Luz + * Copyright (C) 2019-2021 Maximilian Luz */ #ifndef _SURFACE_AGGREGATOR_SSH_MSGB_H diff --git a/drivers/platform/surface/aggregator/ssh_packet_layer.c b/drivers/platform/surface/aggregator/ssh_packet_layer.c index 15d96eac6811..5e08049fc3ac 100644 --- a/drivers/platform/surface/aggregator/ssh_packet_layer.c +++ b/drivers/platform/surface/aggregator/ssh_packet_layer.c @@ -2,7 +2,7 @@ /* * SSH packet transport layer. * - * Copyright (C) 2019-2020 Maximilian Luz + * Copyright (C) 2019-2021 Maximilian Luz */ #include diff --git a/drivers/platform/surface/aggregator/ssh_packet_layer.h b/drivers/platform/surface/aggregator/ssh_packet_layer.h index e8757d03f279..2eb329f0b91a 100644 --- a/drivers/platform/surface/aggregator/ssh_packet_layer.h +++ b/drivers/platform/surface/aggregator/ssh_packet_layer.h @@ -2,7 +2,7 @@ /* * SSH packet transport layer. * - * Copyright (C) 2019-2020 Maximilian Luz + * Copyright (C) 2019-2021 Maximilian Luz */ #ifndef _SURFACE_AGGREGATOR_SSH_PACKET_LAYER_H diff --git a/drivers/platform/surface/aggregator/ssh_parser.c b/drivers/platform/surface/aggregator/ssh_parser.c index e2dead8de94a..b77912f8f13b 100644 --- a/drivers/platform/surface/aggregator/ssh_parser.c +++ b/drivers/platform/surface/aggregator/ssh_parser.c @@ -2,7 +2,7 @@ /* * SSH message parser. * - * Copyright (C) 2019-2020 Maximilian Luz + * Copyright (C) 2019-2021 Maximilian Luz */ #include diff --git a/drivers/platform/surface/aggregator/ssh_parser.h b/drivers/platform/surface/aggregator/ssh_parser.h index 63c38d350988..3bd6e180fd16 100644 --- a/drivers/platform/surface/aggregator/ssh_parser.h +++ b/drivers/platform/surface/aggregator/ssh_parser.h @@ -2,7 +2,7 @@ /* * SSH message parser. * - * Copyright (C) 2019-2020 Maximilian Luz + * Copyright (C) 2019-2021 Maximilian Luz */ #ifndef _SURFACE_AGGREGATOR_SSH_PARSER_H diff --git a/drivers/platform/surface/aggregator/ssh_request_layer.c b/drivers/platform/surface/aggregator/ssh_request_layer.c index 52a83a8fcf82..bfe1aaf38065 100644 --- a/drivers/platform/surface/aggregator/ssh_request_layer.c +++ b/drivers/platform/surface/aggregator/ssh_request_layer.c @@ -2,7 +2,7 @@ /* * SSH request transport layer. * - * Copyright (C) 2019-2020 Maximilian Luz + * Copyright (C) 2019-2021 Maximilian Luz */ #include diff --git a/drivers/platform/surface/aggregator/ssh_request_layer.h b/drivers/platform/surface/aggregator/ssh_request_layer.h index cb35815858d1..9c3cbae2d4bd 100644 --- a/drivers/platform/surface/aggregator/ssh_request_layer.h +++ b/drivers/platform/surface/aggregator/ssh_request_layer.h @@ -2,7 +2,7 @@ /* * SSH request transport layer. * - * Copyright (C) 2019-2020 Maximilian Luz + * Copyright (C) 2019-2021 Maximilian Luz */ #ifndef _SURFACE_AGGREGATOR_SSH_REQUEST_LAYER_H diff --git a/drivers/platform/surface/aggregator/trace.h b/drivers/platform/surface/aggregator/trace.h index eb332bb53ae4..de64cf169060 100644 --- a/drivers/platform/surface/aggregator/trace.h +++ b/drivers/platform/surface/aggregator/trace.h @@ -2,7 +2,7 @@ /* * Trace points for SSAM/SSH. * - * Copyright (C) 2020 Maximilian Luz + * Copyright (C) 2020-2021 Maximilian Luz */ #undef TRACE_SYSTEM diff --git a/include/linux/surface_aggregator/controller.h b/include/linux/surface_aggregator/controller.h index 7965bdc669c5..068e1982ad37 100644 --- a/include/linux/surface_aggregator/controller.h +++ b/include/linux/surface_aggregator/controller.h @@ -6,7 +6,7 @@ * managing access and communication to and from the SSAM EC, as well as main * communication structures and definitions. * - * Copyright (C) 2019-2020 Maximilian Luz + * Copyright (C) 2019-2021 Maximilian Luz */ #ifndef _LINUX_SURFACE_AGGREGATOR_CONTROLLER_H diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h index 6ff9c58b3e17..f636c5310321 100644 --- a/include/linux/surface_aggregator/device.h +++ b/include/linux/surface_aggregator/device.h @@ -7,7 +7,7 @@ * Provides support for non-platform/non-ACPI SSAM clients via dedicated * subsystem. * - * Copyright (C) 2019-2020 Maximilian Luz + * Copyright (C) 2019-2021 Maximilian Luz */ #ifndef _LINUX_SURFACE_AGGREGATOR_DEVICE_H diff --git a/include/linux/surface_aggregator/serial_hub.h b/include/linux/surface_aggregator/serial_hub.h index 64276fbfa1d5..c3de43edcffa 100644 --- a/include/linux/surface_aggregator/serial_hub.h +++ b/include/linux/surface_aggregator/serial_hub.h @@ -6,7 +6,7 @@ * Surface System Aggregator Module (SSAM). Provides the interface for basic * packet- and request-based communication with the SSAM EC via SSH. * - * Copyright (C) 2019-2020 Maximilian Luz + * Copyright (C) 2019-2021 Maximilian Luz */ #ifndef _LINUX_SURFACE_AGGREGATOR_SERIAL_HUB_H From patchwork Fri Jun 4 13:47:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maximilian Luz X-Patchwork-Id: 12299813 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 105A0C47098 for ; Fri, 4 Jun 2021 13:48:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EBF8D613C9 for ; Fri, 4 Jun 2021 13:48:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231171AbhFDNu1 (ORCPT ); Fri, 4 Jun 2021 09:50:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38744 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230522AbhFDNuZ (ORCPT ); Fri, 4 Jun 2021 09:50:25 -0400 Received: from mail-wm1-x333.google.com (mail-wm1-x333.google.com [IPv6:2a00:1450:4864:20::333]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 00DD3C061787; Fri, 4 Jun 2021 06:48:23 -0700 (PDT) Received: by mail-wm1-x333.google.com with SMTP id l11-20020a05600c4f0bb029017a7cd488f5so5694114wmq.0; Fri, 04 Jun 2021 06:48:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=UB5X+DoB5Z0T+zZbOJDPMXCXi5hFubTyMjkjGyFRpCI=; b=unleHltX47NhJzJEIw1AgvHAgU2aLrLgfstZbo1+DYy6K6HfZfh3gW9iDAENiTE+9y pzWPQA+hs5LHbUjU+PqHttSUvyNZnpFwQogGtUyYhrdN3iCLykJ7/GS594VXimnTmSou TaJsDXYD/3uGqA3UHZcGD2FKHk+MwLn26MxiMMcf7SBdG/7uQQbKQWFEdIrwUirgvP7S ToEzo7v9p2kWGHG1Yudxzx9YE3RMp7SqBDEfB3nu9gbPIzahgcjl4a/IUWgetOhPLnzk 3zPcUFC4Db682lfpt6g3chDKVW4MDie50/0Gsjqwts79YCl8oFdlRljim0eFH0k+pAin Wrkg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=UB5X+DoB5Z0T+zZbOJDPMXCXi5hFubTyMjkjGyFRpCI=; b=cJY8+27MyX7Dg9om6pD3YAt7A1FUU/0Bs2TvmvlLXNXhZLvaISG4drdSW8xZhLop6S 5amOVHOlZJyHQzBjesS4lNeykeupizfP+LuF5QXwPJ+Rbi0vvtQoJOORcEogRpgWL+9j am0YRWQPjgLX2VEVgPQNDnkZh4xLMhpRQxfa3CB7yFCxtN8IP82G2G3p+iiSSQc6k9Js vsYfOOzcejVVpbgPnv9mjbPM/4BgwAOcibM56NQeZHJLBWBfvkEhfqb4UWCe1SaCKZbx s31ivU1U5eNJuBAY5uJ1SDQ8qauv6abOdMq8PgwQsDnUMn319yuBwTgeCCmVIBxX0xkt BYBw== X-Gm-Message-State: AOAM5332OvNhCEpAYsWwWOZSpOg8kLCrT5hod3/TmpoMKHZOZvQ6yqEw 39MAjmikh7yUNrDrmpw4C84= X-Google-Smtp-Source: ABdhPJy6EWnOFrKO1sDfrjsf7MhNRg/OVOfCVNqhraXWXBCe3ehs4vkk6lG6MZp+4K07iNG2ophEsg== X-Received: by 2002:a7b:c5d2:: with SMTP id n18mr3800226wmk.97.1622814502380; Fri, 04 Jun 2021 06:48:22 -0700 (PDT) Received: from xws.localdomain (pd9e5aba0.dip0.t-ipconnect.de. [217.229.171.160]) by smtp.gmail.com with ESMTPSA id u16sm7403167wru.56.2021.06.04.06.48.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Jun 2021 06:48:22 -0700 (PDT) From: Maximilian Luz To: Hans de Goede Cc: Maximilian Luz , Mark Gross , Jonathan Corbet , platform-driver-x86@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 4/7] platform/surface: aggregator_cdev: Add support for forwarding events to user-space Date: Fri, 4 Jun 2021 15:47:52 +0200 Message-Id: <20210604134755.535590-5-luzmaximilian@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210604134755.535590-1-luzmaximilian@gmail.com> References: <20210604134755.535590-1-luzmaximilian@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org Currently, debugging unknown events requires writing a custom driver. This is somewhat difficult, slow to adapt, and not entirely user-friendly for quickly trying to figure out things on devices of some third-party user. We can do better. We already have a user-space interface intended for debugging SAM EC requests, so let's add support for receiving events to that. This commit provides support for receiving events by reading from the controller file. It additionally introduces two new IOCTLs to control which event categories will be forwarded. Specifically, a user-space client can specify which target categories it wants to receive events from by registering the corresponding notifier(s) via the IOCTLs and after that, read the received events by reading from the controller device. Signed-off-by: Maximilian Luz Reviewed-by: Hans de Goede --- Changes in v2: - Add missing mutex_destroy() calls in open() failure path --- .../userspace-api/ioctl/ioctl-number.rst | 2 +- .../surface/surface_aggregator_cdev.c | 460 +++++++++++++++++- include/uapi/linux/surface_aggregator/cdev.h | 41 +- 3 files changed, 477 insertions(+), 26 deletions(-) diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst index 9bfc2b510c64..1409e40e6345 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst @@ -325,7 +325,7 @@ Code Seq# Include File Comments 0xA3 90-9F linux/dtlk.h 0xA4 00-1F uapi/linux/tee.h Generic TEE subsystem 0xA4 00-1F uapi/asm/sgx.h -0xA5 01 linux/surface_aggregator/cdev.h Microsoft Surface Platform System Aggregator +0xA5 01-05 linux/surface_aggregator/cdev.h Microsoft Surface Platform System Aggregator 0xA5 20-2F linux/surface_aggregator/dtx.h Microsoft Surface DTX driver diff --git a/drivers/platform/surface/surface_aggregator_cdev.c b/drivers/platform/surface/surface_aggregator_cdev.c index 79e28fab7e40..dcda377896b7 100644 --- a/drivers/platform/surface/surface_aggregator_cdev.c +++ b/drivers/platform/surface/surface_aggregator_cdev.c @@ -3,29 +3,69 @@ * Provides user-space access to the SSAM EC via the /dev/surface/aggregator * misc device. Intended for debugging and development. * - * Copyright (C) 2020 Maximilian Luz + * Copyright (C) 2020-2021 Maximilian Luz */ #include +#include #include +#include #include #include #include #include +#include #include #include #include +#include #include #include +#include #define SSAM_CDEV_DEVICE_NAME "surface_aggregator_cdev" + +/* -- Main structures. ------------------------------------------------------ */ + +enum ssam_cdev_device_state { + SSAM_CDEV_DEVICE_SHUTDOWN_BIT = BIT(0), +}; + struct ssam_cdev { struct kref kref; struct rw_semaphore lock; + + struct device *dev; struct ssam_controller *ctrl; struct miscdevice mdev; + unsigned long flags; + + struct rw_semaphore client_lock; /* Guards client list. */ + struct list_head client_list; +}; + +struct ssam_cdev_client; + +struct ssam_cdev_notifier { + struct ssam_cdev_client *client; + struct ssam_event_notifier nf; +}; + +struct ssam_cdev_client { + struct ssam_cdev *cdev; + struct list_head node; + + struct mutex notifier_lock; /* Guards notifier access for registration */ + struct ssam_cdev_notifier *notifier[SSH_NUM_EVENTS]; + + struct mutex read_lock; /* Guards FIFO buffer read access */ + struct mutex write_lock; /* Guards FIFO buffer write access */ + DECLARE_KFIFO(buffer, u8, 4096); + + wait_queue_head_t waitq; + struct fasync_struct *fasync; }; static void __ssam_cdev_release(struct kref *kref) @@ -47,24 +87,169 @@ static void ssam_cdev_put(struct ssam_cdev *cdev) kref_put(&cdev->kref, __ssam_cdev_release); } -static int ssam_cdev_device_open(struct inode *inode, struct file *filp) + +/* -- Notifier handling. ---------------------------------------------------- */ + +static u32 ssam_cdev_notifier(struct ssam_event_notifier *nf, const struct ssam_event *in) { - struct miscdevice *mdev = filp->private_data; - struct ssam_cdev *cdev = container_of(mdev, struct ssam_cdev, mdev); + struct ssam_cdev_notifier *cdev_nf = container_of(nf, struct ssam_cdev_notifier, nf); + struct ssam_cdev_client *client = cdev_nf->client; + struct ssam_cdev_event event; + size_t n = struct_size(&event, data, in->length); + + /* Translate event. */ + event.target_category = in->target_category; + event.target_id = in->target_id; + event.command_id = in->command_id; + event.instance_id = in->instance_id; + event.length = in->length; + + mutex_lock(&client->write_lock); + + /* Make sure we have enough space. */ + if (kfifo_avail(&client->buffer) < n) { + dev_warn(client->cdev->dev, + "buffer full, dropping event (tc: %#04x, tid: %#04x, cid: %#04x, iid: %#04x)\n", + in->target_category, in->target_id, in->command_id, in->instance_id); + mutex_unlock(&client->write_lock); + return 0; + } - filp->private_data = ssam_cdev_get(cdev); - return stream_open(inode, filp); + /* Copy event header and payload. */ + kfifo_in(&client->buffer, (const u8 *)&event, struct_size(&event, data, 0)); + kfifo_in(&client->buffer, &in->data[0], in->length); + + mutex_unlock(&client->write_lock); + + /* Notify waiting readers. */ + kill_fasync(&client->fasync, SIGIO, POLL_IN); + wake_up_interruptible(&client->waitq); + + /* + * Don't mark events as handled, this is the job of a proper driver and + * not the debugging interface. + */ + return 0; } -static int ssam_cdev_device_release(struct inode *inode, struct file *filp) +static int ssam_cdev_notifier_register(struct ssam_cdev_client *client, u8 tc, int priority) { - ssam_cdev_put(filp->private_data); - return 0; + const u16 rqid = ssh_tc_to_rqid(tc); + const u16 event = ssh_rqid_to_event(rqid); + struct ssam_cdev_notifier *nf; + int status; + + /* Validate notifier target category. */ + if (!ssh_rqid_is_event(rqid)) + return -EINVAL; + + mutex_lock(&client->notifier_lock); + + /* Check if the notifier has already been registered. */ + if (client->notifier[event]) { + mutex_unlock(&client->notifier_lock); + return -EEXIST; + } + + /* Allocate new notifier. */ + nf = kzalloc(sizeof(*nf), GFP_KERNEL); + if (!nf) { + mutex_unlock(&client->notifier_lock); + return -ENOMEM; + } + + /* + * Create a dummy notifier with the minimal required fields for + * observer registration. Note that we can skip fully specifying event + * and registry here as we do not need any matching and use silent + * registration, which does not enable the corresponding event. + */ + nf->client = client; + nf->nf.base.fn = ssam_cdev_notifier; + nf->nf.base.priority = priority; + nf->nf.event.id.target_category = tc; + nf->nf.event.mask = 0; /* Do not do any matching. */ + nf->nf.flags = SSAM_EVENT_NOTIFIER_OBSERVER; + + /* Register notifier. */ + status = ssam_notifier_register(client->cdev->ctrl, &nf->nf); + if (status) + kfree(nf); + else + client->notifier[event] = nf; + + mutex_unlock(&client->notifier_lock); + return status; } -static long ssam_cdev_request(struct ssam_cdev *cdev, unsigned long arg) +static int ssam_cdev_notifier_unregister(struct ssam_cdev_client *client, u8 tc) +{ + const u16 rqid = ssh_tc_to_rqid(tc); + const u16 event = ssh_rqid_to_event(rqid); + int status; + + /* Validate notifier target category. */ + if (!ssh_rqid_is_event(rqid)) + return -EINVAL; + + mutex_lock(&client->notifier_lock); + + /* Check if the notifier is currently registered. */ + if (!client->notifier[event]) { + mutex_unlock(&client->notifier_lock); + return -ENOENT; + } + + /* Unregister and free notifier. */ + status = ssam_notifier_unregister(client->cdev->ctrl, &client->notifier[event]->nf); + kfree(client->notifier[event]); + client->notifier[event] = NULL; + + mutex_unlock(&client->notifier_lock); + return status; +} + +static void ssam_cdev_notifier_unregister_all(struct ssam_cdev_client *client) +{ + int i; + + down_read(&client->cdev->lock); + + /* + * This function may be used during shutdown, thus we need to test for + * cdev->ctrl instead of the SSAM_CDEV_DEVICE_SHUTDOWN_BIT bit. + */ + if (client->cdev->ctrl) { + for (i = 0; i < SSH_NUM_EVENTS; i++) + ssam_cdev_notifier_unregister(client, i + 1); + + } else { + int count = 0; + + /* + * Device has been shut down. Any notifier remaining is a bug, + * so warn about that as this would otherwise hardly be + * noticeable. Nevertheless, free them as well. + */ + mutex_lock(&client->notifier_lock); + for (i = 0; i < SSH_NUM_EVENTS; i++) { + count += !!(client->notifier[i]); + kfree(client->notifier[i]); + client->notifier[i] = NULL; + } + mutex_unlock(&client->notifier_lock); + + WARN_ON(count > 0); + } + + up_read(&client->cdev->lock); +} + + +/* -- IOCTL functions. ------------------------------------------------------ */ + +static long ssam_cdev_request(struct ssam_cdev_client *client, struct ssam_cdev_request __user *r) { - struct ssam_cdev_request __user *r; struct ssam_cdev_request rqst; struct ssam_request spec = {}; struct ssam_response rsp = {}; @@ -72,7 +257,6 @@ static long ssam_cdev_request(struct ssam_cdev *cdev, unsigned long arg) void __user *rspdata; int status = 0, ret = 0, tmp; - r = (struct ssam_cdev_request __user *)arg; ret = copy_struct_from_user(&rqst, sizeof(rqst), r, sizeof(*r)); if (ret) goto out; @@ -152,7 +336,7 @@ static long ssam_cdev_request(struct ssam_cdev *cdev, unsigned long arg) } /* Perform request. */ - status = ssam_request_sync(cdev->ctrl, &spec, &rsp); + status = ssam_request_sync(client->cdev->ctrl, &spec, &rsp); if (status) goto out; @@ -177,48 +361,247 @@ static long ssam_cdev_request(struct ssam_cdev *cdev, unsigned long arg) return ret; } -static long __ssam_cdev_device_ioctl(struct ssam_cdev *cdev, unsigned int cmd, +static long ssam_cdev_notif_register(struct ssam_cdev_client *client, + const struct ssam_cdev_notifier_desc __user *d) +{ + struct ssam_cdev_notifier_desc desc; + long ret; + + ret = copy_struct_from_user(&desc, sizeof(desc), d, sizeof(*d)); + if (ret) + return ret; + + return ssam_cdev_notifier_register(client, desc.target_category, desc.priority); +} + +static long ssam_cdev_notif_unregister(struct ssam_cdev_client *client, + const struct ssam_cdev_notifier_desc __user *d) +{ + struct ssam_cdev_notifier_desc desc; + long ret; + + ret = copy_struct_from_user(&desc, sizeof(desc), d, sizeof(*d)); + if (ret) + return ret; + + return ssam_cdev_notifier_unregister(client, desc.target_category); +} + + +/* -- File operations. ------------------------------------------------------ */ + +static int ssam_cdev_device_open(struct inode *inode, struct file *filp) +{ + struct miscdevice *mdev = filp->private_data; + struct ssam_cdev_client *client; + struct ssam_cdev *cdev = container_of(mdev, struct ssam_cdev, mdev); + + /* Initialize client */ + client = vzalloc(sizeof(*client)); + if (!client) + return -ENOMEM; + + client->cdev = ssam_cdev_get(cdev); + + INIT_LIST_HEAD(&client->node); + + mutex_init(&client->notifier_lock); + + mutex_init(&client->read_lock); + mutex_init(&client->write_lock); + INIT_KFIFO(client->buffer); + init_waitqueue_head(&client->waitq); + + filp->private_data = client; + + /* Attach client. */ + down_write(&cdev->client_lock); + + if (test_bit(SSAM_CDEV_DEVICE_SHUTDOWN_BIT, &cdev->flags)) { + up_write(&cdev->client_lock); + mutex_destroy(&client->write_lock); + mutex_destroy(&client->read_lock); + mutex_destroy(&client->notifier_lock); + ssam_cdev_put(client->cdev); + vfree(client); + return -ENODEV; + } + list_add_tail(&client->node, &cdev->client_list); + + up_write(&cdev->client_lock); + + stream_open(inode, filp); + return 0; +} + +static int ssam_cdev_device_release(struct inode *inode, struct file *filp) +{ + struct ssam_cdev_client *client = filp->private_data; + + /* Force-unregister all remaining notifiers of this client. */ + ssam_cdev_notifier_unregister_all(client); + + /* Detach client. */ + down_write(&client->cdev->client_lock); + list_del(&client->node); + up_write(&client->cdev->client_lock); + + /* Free client. */ + mutex_destroy(&client->write_lock); + mutex_destroy(&client->read_lock); + + mutex_destroy(&client->notifier_lock); + + ssam_cdev_put(client->cdev); + vfree(client); + + return 0; +} + +static long __ssam_cdev_device_ioctl(struct ssam_cdev_client *client, unsigned int cmd, unsigned long arg) { switch (cmd) { case SSAM_CDEV_REQUEST: - return ssam_cdev_request(cdev, arg); + return ssam_cdev_request(client, (struct ssam_cdev_request __user *)arg); + + case SSAM_CDEV_NOTIF_REGISTER: + return ssam_cdev_notif_register(client, + (struct ssam_cdev_notifier_desc __user *)arg); + + case SSAM_CDEV_NOTIF_UNREGISTER: + return ssam_cdev_notif_unregister(client, + (struct ssam_cdev_notifier_desc __user *)arg); default: return -ENOTTY; } } -static long ssam_cdev_device_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) +static long ssam_cdev_device_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct ssam_cdev *cdev = file->private_data; + struct ssam_cdev_client *client = file->private_data; long status; /* Ensure that controller is valid for as long as we need it. */ + if (down_read_killable(&client->cdev->lock)) + return -ERESTARTSYS; + + if (test_bit(SSAM_CDEV_DEVICE_SHUTDOWN_BIT, &client->cdev->flags)) { + up_read(&client->cdev->lock); + return -ENODEV; + } + + status = __ssam_cdev_device_ioctl(client, cmd, arg); + + up_read(&client->cdev->lock); + return status; +} + +static ssize_t ssam_cdev_read(struct file *file, char __user *buf, size_t count, loff_t *offs) +{ + struct ssam_cdev_client *client = file->private_data; + struct ssam_cdev *cdev = client->cdev; + unsigned int copied; + int status = 0; + if (down_read_killable(&cdev->lock)) return -ERESTARTSYS; - if (!cdev->ctrl) { + /* Make sure we're not shut down. */ + if (test_bit(SSAM_CDEV_DEVICE_SHUTDOWN_BIT, &cdev->flags)) { up_read(&cdev->lock); return -ENODEV; } - status = __ssam_cdev_device_ioctl(cdev, cmd, arg); + do { + /* Check availability, wait if necessary. */ + if (kfifo_is_empty(&client->buffer)) { + up_read(&cdev->lock); + + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + + status = wait_event_interruptible(client->waitq, + !kfifo_is_empty(&client->buffer) || + test_bit(SSAM_CDEV_DEVICE_SHUTDOWN_BIT, + &cdev->flags)); + if (status < 0) + return status; + + if (down_read_killable(&cdev->lock)) + return -ERESTARTSYS; + + /* Need to check that we're not shut down again. */ + if (test_bit(SSAM_CDEV_DEVICE_SHUTDOWN_BIT, &cdev->flags)) { + up_read(&cdev->lock); + return -ENODEV; + } + } + + /* Try to read from FIFO. */ + if (mutex_lock_interruptible(&client->read_lock)) { + up_read(&cdev->lock); + return -ERESTARTSYS; + } + + status = kfifo_to_user(&client->buffer, buf, count, &copied); + mutex_unlock(&client->read_lock); + + if (status < 0) { + up_read(&cdev->lock); + return status; + } + + /* We might not have gotten anything, check this here. */ + if (copied == 0 && (file->f_flags & O_NONBLOCK)) { + up_read(&cdev->lock); + return -EAGAIN; + } + } while (copied == 0); up_read(&cdev->lock); - return status; + return copied; +} + +static __poll_t ssam_cdev_poll(struct file *file, struct poll_table_struct *pt) +{ + struct ssam_cdev_client *client = file->private_data; + __poll_t events = 0; + + if (test_bit(SSAM_CDEV_DEVICE_SHUTDOWN_BIT, &client->cdev->flags)) + return EPOLLHUP | EPOLLERR; + + poll_wait(file, &client->waitq, pt); + + if (!kfifo_is_empty(&client->buffer)) + events |= EPOLLIN | EPOLLRDNORM; + + return events; +} + +static int ssam_cdev_fasync(int fd, struct file *file, int on) +{ + struct ssam_cdev_client *client = file->private_data; + + return fasync_helper(fd, file, on, &client->fasync); } static const struct file_operations ssam_controller_fops = { .owner = THIS_MODULE, .open = ssam_cdev_device_open, .release = ssam_cdev_device_release, + .read = ssam_cdev_read, + .poll = ssam_cdev_poll, + .fasync = ssam_cdev_fasync, .unlocked_ioctl = ssam_cdev_device_ioctl, .compat_ioctl = ssam_cdev_device_ioctl, - .llseek = noop_llseek, + .llseek = no_llseek, }; + +/* -- Device and driver setup ----------------------------------------------- */ + static int ssam_dbg_device_probe(struct platform_device *pdev) { struct ssam_controller *ctrl; @@ -236,6 +619,7 @@ static int ssam_dbg_device_probe(struct platform_device *pdev) kref_init(&cdev->kref); init_rwsem(&cdev->lock); cdev->ctrl = ctrl; + cdev->dev = &pdev->dev; cdev->mdev.parent = &pdev->dev; cdev->mdev.minor = MISC_DYNAMIC_MINOR; @@ -243,6 +627,9 @@ static int ssam_dbg_device_probe(struct platform_device *pdev) cdev->mdev.nodename = "surface/aggregator"; cdev->mdev.fops = &ssam_controller_fops; + init_rwsem(&cdev->client_lock); + INIT_LIST_HEAD(&cdev->client_list); + status = misc_register(&cdev->mdev); if (status) { kfree(cdev); @@ -256,8 +643,32 @@ static int ssam_dbg_device_probe(struct platform_device *pdev) static int ssam_dbg_device_remove(struct platform_device *pdev) { struct ssam_cdev *cdev = platform_get_drvdata(pdev); + struct ssam_cdev_client *client; - misc_deregister(&cdev->mdev); + /* + * Mark device as shut-down. Prevent new clients from being added and + * new operations from being executed. + */ + set_bit(SSAM_CDEV_DEVICE_SHUTDOWN_BIT, &cdev->flags); + + down_write(&cdev->client_lock); + + /* Remove all notifiers registered by us. */ + list_for_each_entry(client, &cdev->client_list, node) { + ssam_cdev_notifier_unregister_all(client); + } + + /* Wake up async clients. */ + list_for_each_entry(client, &cdev->client_list, node) { + kill_fasync(&client->fasync, SIGIO, POLL_HUP); + } + + /* Wake up blocking clients. */ + list_for_each_entry(client, &cdev->client_list, node) { + wake_up_interruptible(&client->waitq); + } + + up_write(&cdev->client_lock); /* * The controller is only guaranteed to be valid for as long as the @@ -266,8 +677,11 @@ static int ssam_dbg_device_remove(struct platform_device *pdev) */ down_write(&cdev->lock); cdev->ctrl = NULL; + cdev->dev = NULL; up_write(&cdev->lock); + misc_deregister(&cdev->mdev); + ssam_cdev_put(cdev); return 0; } diff --git a/include/uapi/linux/surface_aggregator/cdev.h b/include/uapi/linux/surface_aggregator/cdev.h index fbcce04abfe9..4f393fafc235 100644 --- a/include/uapi/linux/surface_aggregator/cdev.h +++ b/include/uapi/linux/surface_aggregator/cdev.h @@ -6,7 +6,7 @@ * device. This device provides direct user-space access to the SSAM EC. * Intended for debugging and development. * - * Copyright (C) 2020 Maximilian Luz + * Copyright (C) 2020-2021 Maximilian Luz */ #ifndef _UAPI_LINUX_SURFACE_AGGREGATOR_CDEV_H @@ -73,6 +73,43 @@ struct ssam_cdev_request { } response; } __attribute__((__packed__)); -#define SSAM_CDEV_REQUEST _IOWR(0xA5, 1, struct ssam_cdev_request) +/** + * struct ssam_cdev_notifier_desc - Notifier descriptor. + * @priority: Priority value determining the order in which notifier + * callbacks will be called. A higher value means higher + * priority, i.e. the associated callback will be executed + * earlier than other (lower priority) callbacks. + * @target_category: The event target category for which this notifier should + * receive events. + * + * Specifies the notifier that should be registered or unregistered, + * specifically with which priority and for which target category of events. + */ +struct ssam_cdev_notifier_desc { + __s32 priority; + __u8 target_category; +} __attribute__((__packed__)); + +/** + * struct ssam_cdev_event - SSAM event sent by the EC. + * @target_category: Target category of the event source. See &enum ssam_ssh_tc. + * @target_id: Target ID of the event source. + * @command_id: Command ID of the event. + * @instance_id: Instance ID of the event source. + * @length: Length of the event payload in bytes. + * @data: Event payload data. + */ +struct ssam_cdev_event { + __u8 target_category; + __u8 target_id; + __u8 command_id; + __u8 instance_id; + __u16 length; + __u8 data[]; +} __attribute__((__packed__)); + +#define SSAM_CDEV_REQUEST _IOWR(0xA5, 1, struct ssam_cdev_request) +#define SSAM_CDEV_NOTIF_REGISTER _IOW(0xA5, 2, struct ssam_cdev_notifier_desc) +#define SSAM_CDEV_NOTIF_UNREGISTER _IOW(0xA5, 3, struct ssam_cdev_notifier_desc) #endif /* _UAPI_LINUX_SURFACE_AGGREGATOR_CDEV_H */ From patchwork Fri Jun 4 13:47:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maximilian Luz X-Patchwork-Id: 12299803 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 108DFC07E94 for ; Fri, 4 Jun 2021 13:48:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id ED75B613FA for ; Fri, 4 Jun 2021 13:48:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230331AbhFDNuL (ORCPT ); Fri, 4 Jun 2021 09:50:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38748 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230142AbhFDNuL (ORCPT ); Fri, 4 Jun 2021 09:50:11 -0400 Received: from mail-wr1-x432.google.com (mail-wr1-x432.google.com [IPv6:2a00:1450:4864:20::432]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CBE05C061789; Fri, 4 Jun 2021 06:48:24 -0700 (PDT) Received: by mail-wr1-x432.google.com with SMTP id m18so9400778wrv.2; Fri, 04 Jun 2021 06:48:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=0hblWKhhVFj2BU43fxgvQPVXjbtJ6ZeAeWI+WSD8RhA=; b=u7ST3EdEgOaOIXWFvUof1gorxmA3TYZ/mgsKTduDOVlRZXjTEThZG0k/1Buh2C7a1+ KufeqTJhSLIJD5YlfWbrDm52LwUVlqAnuGpMy9fIEHvTNQ/8pmYBCMnWihNPvAVHn+DN BfpH8suKSHb3gFUrbJVAo9Pq+fHZuVc/gAvQ4GhAT03Yen7OCMuJoPvmiYWXrhAxZ5yD vf3s1yjQzAF2KLwugFX7mCd8+cNard654K2AqyuYnXAk29dfXaPCZBO6cgnzCRWXIhG6 kLN5+gmweacY7yZbTbGAEiRZiJWCyVkhNI/HyhlmdaFEBVj+JrQn1S2lJD0y+TC+gM/+ V3PQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=0hblWKhhVFj2BU43fxgvQPVXjbtJ6ZeAeWI+WSD8RhA=; b=hmPUYds/yGIWftTeMrnUdc/m72dkTiBPkLwQTXduq3aZkRxTNgqrTbd64d3OuJJw3Z l0dMIAgnmz3eRmwUCy/5Iea4FXj/KjgNXO+JwKvL3OApL4rq0S3kgFySnYitt3/I9lRd FpC4moj0Kh4yUj0zvVDN3bcfAmOI7HRf1+1yWQrKH7PUNyG+XRcMmr4nhqfDeP7YpZ9C pRyrapJBhO+vWCO4fNp45fCVfaGopsn+QcQMdkJjlgFM7b+SCw0aidvtGCUAihRXK/gg zhi6yLsDHMaOzDAbHZSZVdo5S2JvWqRfBN304FBoseN/+ecEUSoYz9o1dBlfzaKvgISj vC1w== X-Gm-Message-State: AOAM533opuM7PCguvcTDOkUJ3VKTrEuX0PHErAj+3sQr4/pLpMQUnbaS Y/dZbeOZGChPqPiQeflpO+A= X-Google-Smtp-Source: ABdhPJwYwkQQL+v1anJK+ywKT4dJxqIye3itLfWqmMOGam6q54ZtNaBdTvaE2uD8+I/vbiE6b74YPg== X-Received: by 2002:a5d:5243:: with SMTP id k3mr4102693wrc.19.1622814503396; Fri, 04 Jun 2021 06:48:23 -0700 (PDT) Received: from xws.localdomain (pd9e5aba0.dip0.t-ipconnect.de. [217.229.171.160]) by smtp.gmail.com with ESMTPSA id u16sm7403167wru.56.2021.06.04.06.48.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Jun 2021 06:48:22 -0700 (PDT) From: Maximilian Luz To: Hans de Goede Cc: Maximilian Luz , Mark Gross , platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 5/7] platform/surface: aggregator_cdev: Allow enabling of events from user-space Date: Fri, 4 Jun 2021 15:47:53 +0200 Message-Id: <20210604134755.535590-6-luzmaximilian@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210604134755.535590-1-luzmaximilian@gmail.com> References: <20210604134755.535590-1-luzmaximilian@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org 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 --- Changes in v2: - None --- .../surface/surface_aggregator_cdev.c | 58 +++++++++++++++++++ include/uapi/linux/surface_aggregator/cdev.h | 32 ++++++++++ 2 files changed, 90 insertions(+) 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; } diff --git a/include/uapi/linux/surface_aggregator/cdev.h b/include/uapi/linux/surface_aggregator/cdev.h index 4f393fafc235..08f46b60b151 100644 --- a/include/uapi/linux/surface_aggregator/cdev.h +++ b/include/uapi/linux/surface_aggregator/cdev.h @@ -90,6 +90,36 @@ struct ssam_cdev_notifier_desc { __u8 target_category; } __attribute__((__packed__)); +/** + * struct ssam_cdev_event_desc - Event descriptor. + * @reg: Registry via which the event will be enabled/disabled. + * @reg.target_category: Target category for the event registry requests. + * @reg.target_id: Target ID for the event registry requests. + * @reg.cid_enable: Command ID for the event-enable request. + * @reg.cid_disable: Command ID for the event-disable request. + * @id: ID specifying the event. + * @id.target_category: Target category of the event source. + * @id.instance: Instance ID of the event source. + * @flags: Flags used for enabling the event. + * + * Specifies which event should be enabled/disabled and how to do that. + */ +struct ssam_cdev_event_desc { + struct { + __u8 target_category; + __u8 target_id; + __u8 cid_enable; + __u8 cid_disable; + } reg; + + struct { + __u8 target_category; + __u8 instance; + } id; + + __u8 flags; +} __attribute__((__packed__)); + /** * struct ssam_cdev_event - SSAM event sent by the EC. * @target_category: Target category of the event source. See &enum ssam_ssh_tc. @@ -111,5 +141,7 @@ struct ssam_cdev_event { #define SSAM_CDEV_REQUEST _IOWR(0xA5, 1, struct ssam_cdev_request) #define SSAM_CDEV_NOTIF_REGISTER _IOW(0xA5, 2, struct ssam_cdev_notifier_desc) #define SSAM_CDEV_NOTIF_UNREGISTER _IOW(0xA5, 3, struct ssam_cdev_notifier_desc) +#define SSAM_CDEV_EVENT_ENABLE _IOW(0xA5, 4, struct ssam_cdev_event_desc) +#define SSAM_CDEV_EVENT_DISABLE _IOW(0xA5, 5, struct ssam_cdev_event_desc) #endif /* _UAPI_LINUX_SURFACE_AGGREGATOR_CDEV_H */ From patchwork Fri Jun 4 13:47:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maximilian Luz X-Patchwork-Id: 12299817 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E88F1C07E94 for ; Fri, 4 Jun 2021 13:49:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CD68B613C9 for ; Fri, 4 Jun 2021 13:49:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230262AbhFDNvV (ORCPT ); Fri, 4 Jun 2021 09:51:21 -0400 Received: from mail-wm1-f43.google.com ([209.85.128.43]:46059 "EHLO mail-wm1-f43.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230124AbhFDNvU (ORCPT ); Fri, 4 Jun 2021 09:51:20 -0400 Received: by mail-wm1-f43.google.com with SMTP id v206-20020a1cded70000b02901a586d3fa23so1385295wmg.4; Fri, 04 Jun 2021 06:49:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=n+j7xPh36RHrF3IBVvuTQ/zEy/iKAdtrHI17EQxJYRo=; b=EB0x89s2Z0E41XJWL3SfZu8ewJKbK4DxcphdKJZskytUjMsUA4K8xVsbrz9xeKwyiU 90Fy/XLMqB9DE2ZxguX8S83Vfofr+MdT/s/Hk5G/UWGcGL79usm4uMYiI+XI8AnxKVmp T3bvhfQqyZiN0UgLvDGkU4SOfhEpaScdV+PZt4EMYlYpXTvhIJWxv7uVGgWI6+pEEKDW /dqq2B63PG6ifvVdGNC+ifLXRkmYkG5oFZRc8tv6CF2fXb8TghhtomGSV2yY8441+q51 e2ysc7OKxQxb5mVhcGFk/YIavQk5M3GI2zwWL4EynriorSRvt04Q0V7mErE2QHNY0Fj5 w5Vw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=n+j7xPh36RHrF3IBVvuTQ/zEy/iKAdtrHI17EQxJYRo=; b=GGGwQr48xFhPMy8N3/gioBlZ/WXFl/jUMoVm9gXyKWJozTWdKkypGpl6LKBZqfqV9d snyHJd2tEdIdCquXGh/IlfeDcyTJ/K0aMFEpJzqpvzJnK0w04iUMlTMQLRXn9OJSDCzV G2c3ZN3ljns6MOzkEtMJMgQnpgE/jVJizOkN400lx+UGUh5NaTXEmq2oS/o9HSOpM9+Z ICLbbLobApObRFgK+aOBHds5ci77Tlebu0Pe3Yul5ekXgaQvdkTbzhCFnVfrsbXFvTF0 nCeP2BPCK2cWWXRg5bJ6AnsdeQx0XkxeNWeEsbbssmLVALbWadfKa8KDgkSzHaSQRnLr rnIA== X-Gm-Message-State: AOAM533cFLEn7PVUiNchulvi/3xB56otuIBRziQuXXBgoaTh+6OiaSRe NC3WUWPVXXAx5bW8xS4Y2fE= X-Google-Smtp-Source: ABdhPJyaUo5gTrCuRZs6OO9gx6CoesqMOGQtzdBiwj8o/aYuQPotct6ICXexQ9qkJBRIkO1lKaQ3eQ== X-Received: by 2002:a05:600c:3789:: with SMTP id o9mr3866409wmr.78.1622814504376; Fri, 04 Jun 2021 06:48:24 -0700 (PDT) Received: from xws.localdomain (pd9e5aba0.dip0.t-ipconnect.de. [217.229.171.160]) by smtp.gmail.com with ESMTPSA id u16sm7403167wru.56.2021.06.04.06.48.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Jun 2021 06:48:23 -0700 (PDT) From: Maximilian Luz To: Hans de Goede Cc: Maximilian Luz , Mark Gross , platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 6/7] platform/surface: aggregator_cdev: Add lockdep support Date: Fri, 4 Jun 2021 15:47:54 +0200 Message-Id: <20210604134755.535590-7-luzmaximilian@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210604134755.535590-1-luzmaximilian@gmail.com> References: <20210604134755.535590-1-luzmaximilian@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org Mark functions with locking requirements via the corresponding lockdep calls for debugging and documentary purposes. Signed-off-by: Maximilian Luz Reviewed-by: Hans de Goede --- Changes in v2: - None --- .../platform/surface/surface_aggregator_cdev.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/platform/surface/surface_aggregator_cdev.c b/drivers/platform/surface/surface_aggregator_cdev.c index 7b86b36eaaa0..30fb50fde450 100644 --- a/drivers/platform/surface/surface_aggregator_cdev.c +++ b/drivers/platform/surface/surface_aggregator_cdev.c @@ -139,6 +139,8 @@ static int ssam_cdev_notifier_register(struct ssam_cdev_client *client, u8 tc, i struct ssam_cdev_notifier *nf; int status; + lockdep_assert_held_read(&client->cdev->lock); + /* Validate notifier target category. */ if (!ssh_rqid_is_event(rqid)) return -EINVAL; @@ -188,6 +190,8 @@ static int ssam_cdev_notifier_unregister(struct ssam_cdev_client *client, u8 tc) const u16 event = ssh_rqid_to_event(rqid); int status; + lockdep_assert_held_read(&client->cdev->lock); + /* Validate notifier target category. */ if (!ssh_rqid_is_event(rqid)) return -EINVAL; @@ -257,6 +261,8 @@ static long ssam_cdev_request(struct ssam_cdev_client *client, struct ssam_cdev_ void __user *rspdata; int status = 0, ret = 0, tmp; + lockdep_assert_held_read(&client->cdev->lock); + ret = copy_struct_from_user(&rqst, sizeof(rqst), r, sizeof(*r)); if (ret) goto out; @@ -367,6 +373,8 @@ static long ssam_cdev_notif_register(struct ssam_cdev_client *client, struct ssam_cdev_notifier_desc desc; long ret; + lockdep_assert_held_read(&client->cdev->lock); + ret = copy_struct_from_user(&desc, sizeof(desc), d, sizeof(*d)); if (ret) return ret; @@ -380,6 +388,8 @@ static long ssam_cdev_notif_unregister(struct ssam_cdev_client *client, struct ssam_cdev_notifier_desc desc; long ret; + lockdep_assert_held_read(&client->cdev->lock); + ret = copy_struct_from_user(&desc, sizeof(desc), d, sizeof(*d)); if (ret) return ret; @@ -395,6 +405,8 @@ static long ssam_cdev_event_enable(struct ssam_cdev_client *client, struct ssam_event_id id; long ret; + lockdep_assert_held_read(&client->cdev->lock); + /* Read descriptor from user-space. */ ret = copy_struct_from_user(&desc, sizeof(desc), d, sizeof(*d)); if (ret) @@ -421,6 +433,8 @@ static long ssam_cdev_event_disable(struct ssam_cdev_client *client, struct ssam_event_id id; long ret; + lockdep_assert_held_read(&client->cdev->lock); + /* Read descriptor from user-space. */ ret = copy_struct_from_user(&desc, sizeof(desc), d, sizeof(*d)); if (ret) @@ -513,6 +527,8 @@ static int ssam_cdev_device_release(struct inode *inode, struct file *filp) static long __ssam_cdev_device_ioctl(struct ssam_cdev_client *client, unsigned int cmd, unsigned long arg) { + lockdep_assert_held_read(&client->cdev->lock); + switch (cmd) { case SSAM_CDEV_REQUEST: return ssam_cdev_request(client, (struct ssam_cdev_request __user *)arg); From patchwork Fri Jun 4 13:47:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maximilian Luz X-Patchwork-Id: 12299805 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-20.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,MENTIONS_GIT_HOSTING,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1E24DC47098 for ; Fri, 4 Jun 2021 13:48:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EA5AE61402 for ; Fri, 4 Jun 2021 13:48:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230366AbhFDNuO (ORCPT ); Fri, 4 Jun 2021 09:50:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38760 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230142AbhFDNuN (ORCPT ); Fri, 4 Jun 2021 09:50:13 -0400 Received: from mail-wr1-x432.google.com (mail-wr1-x432.google.com [IPv6:2a00:1450:4864:20::432]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BA248C061789; Fri, 4 Jun 2021 06:48:26 -0700 (PDT) Received: by mail-wr1-x432.google.com with SMTP id l2so9405289wrw.6; Fri, 04 Jun 2021 06:48:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=6krBnFnbTexLeYVxG8AbFbd9NK8E8A28cizYGAD8aHQ=; b=GUZTByC2w73LEV/rF5oe9BKwqj+f0JyGdXjqeHM7uE85mLXvaiEoEHmTi63HrincMB QhbBYcEi6OfIeVExEd1ojfxqhQr0VAeAAOxVUGDM9wEMTi2DMli2Sk4VcGun4oObiOCn p3n9p0Lq4baPRnRXmLZzycUZ92IKc9auEgAzXRlioqaij+u5IUONlCF+6NfFnvgY3TMx whvInVSPvP3YmnpRdfchDjGjkLTTE2n8j4xgAbcietPjZKzcfriNQzZMkAukZ5WNMG5x WH5604xXWR7MRECJ+o9xYYm0m0jjHACeTTRLGXGuOdn/s+EagG630lH7eoFeKJwfmDVi l3tg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=6krBnFnbTexLeYVxG8AbFbd9NK8E8A28cizYGAD8aHQ=; b=hIF9R1AfgLxgg6iO/PO8YM+zrxcu/yEIvXy18x8c84w9uAoWxlLs7lSjEDt2PtoDBk YLjlGRmRhOKLbGC3R6Y+rtHHakSU6w9LiQkWQBgbcoQsMHKWjK3lwgm1ulGebKFXQj9t pGeqRetuU2h6C14y62PJz2XHTvbj8AozDj+jF0OL26BpBiTTiScYGo2Njg5lYkkuGvna 2uD1jS7R9aVOitj6c9Z8aBV8oTlr1YiA1Pn+81cOns/WVijDNd6+1N21zhN6P1EhvMjx 8JwuBDwTQ7bzVfbS/SWKD1UK7ix4Mc5J38XOqVK+qobbcdn8EwS65P7FPbTuj8BbK8rP 9c6Q== X-Gm-Message-State: AOAM532kM26acrx+XFSasBIVAE4SGD+/vJY/JuLXmeaEiagCsmoCdzlk /Ai1wGNgu1wBOo1l4vELFB4= X-Google-Smtp-Source: ABdhPJxg2cq/v9q3DMgdXZaHzRqz5QNMu0IoE6u1drW4SL3CFRp6Q3qz5mlvc4w2P8z54UF4O6Gatw== X-Received: by 2002:adf:efca:: with SMTP id i10mr4058874wrp.139.1622814505362; Fri, 04 Jun 2021 06:48:25 -0700 (PDT) Received: from xws.localdomain (pd9e5aba0.dip0.t-ipconnect.de. [217.229.171.160]) by smtp.gmail.com with ESMTPSA id u16sm7403167wru.56.2021.06.04.06.48.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Jun 2021 06:48:25 -0700 (PDT) From: Maximilian Luz To: Hans de Goede Cc: Maximilian Luz , Mark Gross , Jonathan Corbet , platform-driver-x86@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 7/7] docs: driver-api: Update Surface Aggregator user-space interface documentation Date: Fri, 4 Jun 2021 15:47:55 +0200 Message-Id: <20210604134755.535590-8-luzmaximilian@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210604134755.535590-1-luzmaximilian@gmail.com> References: <20210604134755.535590-1-luzmaximilian@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org Update the controller-device user-space interface (cdev) documentation for the newly introduced IOCTLs and event interface. Signed-off-by: Maximilian Luz Reviewed-by: Hans de Goede --- Changes in v2: - None --- .../surface_aggregator/clients/cdev.rst | 127 +++++++++++++++++- 1 file changed, 122 insertions(+), 5 deletions(-) diff --git a/Documentation/driver-api/surface_aggregator/clients/cdev.rst b/Documentation/driver-api/surface_aggregator/clients/cdev.rst index 248c1372d879..0134a841a079 100644 --- a/Documentation/driver-api/surface_aggregator/clients/cdev.rst +++ b/Documentation/driver-api/surface_aggregator/clients/cdev.rst @@ -1,9 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0+ -.. |u8| replace:: :c:type:`u8 ` -.. |u16| replace:: :c:type:`u16 ` .. |ssam_cdev_request| replace:: :c:type:`struct ssam_cdev_request ` .. |ssam_cdev_request_flags| replace:: :c:type:`enum ssam_cdev_request_flags ` +.. |ssam_cdev_event| replace:: :c:type:`struct ssam_cdev_event ` ============================== User-Space EC Interface (cdev) @@ -23,6 +22,40 @@ These IOCTLs and their respective input/output parameter structs are defined in A small python library and scripts for accessing this interface can be found at https://github.com/linux-surface/surface-aggregator-module/tree/master/scripts/ssam. +.. contents:: + + +Receiving Events +================ + +Events can be received by reading from the device-file. The are represented by +the |ssam_cdev_event| datatype. + +Before events are available to be read, however, the desired notifiers must be +registered via the ``SSAM_CDEV_NOTIF_REGISTER`` IOCTL. Notifiers are, in +essence, callbacks, called when the EC sends an event. They are, in this +interface, associated with a specific target category and device-file-instance. +They forward any event of this category to the buffer of the corresponding +instance, from which it can then be read. + +Notifiers themselves do not enable events on the EC. Thus, it may additionally +be necessary to enable events via the ``SSAM_CDEV_EVENT_ENABLE`` IOCTL. While +notifiers work per-client (i.e. per-device-file-instance), events are enabled +globally, for the EC and all of its clients (regardless of userspace or +non-userspace). The ``SSAM_CDEV_EVENT_ENABLE`` and ``SSAM_CDEV_EVENT_DISABLE`` +IOCTLs take care of reference counting the events, such that an event is +enabled as long as there is a client that has requested it. + +Note that enabled events are not automatically disabled once the client +instance is closed. Therefore any client process (or group of processes) should +balance their event enable calls with the corresponding event disable calls. It +is, however, perfectly valid to enable and disable events on different client +instances. For example, it is valid to set up notifiers and read events on +client instance ``A``, enable those events on instance ``B`` (note that these +will also be received by A since events are enabled/disabled globally), and +after no more events are desired, disable the previously enabled events via +instance ``C``. + Controller IOCTLs ================= @@ -45,9 +78,33 @@ The following IOCTLs are provided: - ``REQUEST`` - Perform synchronous SAM request. + * - ``0xA5`` + - ``2`` + - ``W`` + - ``NOTIF_REGISTER`` + - Register event notifier. -``REQUEST`` ------------ + * - ``0xA5`` + - ``3`` + - ``W`` + - ``NOTIF_UNREGISTER`` + - Unregister event notifier. + + * - ``0xA5`` + - ``4`` + - ``W`` + - ``EVENT_ENABLE`` + - Enable event source. + + * - ``0xA5`` + - ``5`` + - ``W`` + - ``EVENT_DISABLE`` + - Disable event source. + + +``SSAM_CDEV_REQUEST`` +--------------------- Defined as ``_IOWR(0xA5, 1, struct ssam_cdev_request)``. @@ -82,6 +139,66 @@ submitted, and completed (i.e. handed back to user-space) successfully from inside the IOCTL, but the request ``status`` member may still be negative in case the actual execution of the request failed after it has been submitted. -A full definition of the argument struct is provided below: +A full definition of the argument struct is provided below. + +``SSAM_CDEV_NOTIF_REGISTER`` +---------------------------- + +Defined as ``_IOW(0xA5, 2, struct ssam_cdev_notifier_desc)``. + +Register a notifier for the event target category specified in the given +notifier description with the specified priority. Notifiers registration is +required to receive events, but does not enable events themselves. After a +notifier for a specific target category has been registered, all events of that +category will be forwarded to the userspace client and can then be read from +the device file instance. Note that events may have to be enabled, e.g. via the +``SSAM_CDEV_EVENT_ENABLE`` IOCTL, before the EC will send them. + +Only one notifier can be registered per target category and client instance. If +a notifier has already been registered, this IOCTL will fail with ``-EEXIST``. + +Notifiers will automatically be removed when the device file instance is +closed. + +``SSAM_CDEV_NOTIF_UNREGISTER`` +------------------------------ + +Defined as ``_IOW(0xA5, 3, struct ssam_cdev_notifier_desc)``. + +Unregisters the notifier associated with the specified target category. The +priority field will be ignored by this IOCTL. If no notifier has been +registered for this client instance and the given category, this IOCTL will +fail with ``-ENOENT``. + +``SSAM_CDEV_EVENT_ENABLE`` +-------------------------- + +Defined as ``_IOW(0xA5, 4, struct ssam_cdev_event_desc)``. + +Enable the event associated with the given event descriptor. + +Note that this call will not register a notifier itself, it will only enable +events on the controller. If you want to receive events by reading from the +device file, you will need to register the corresponding notifier(s) on that +instance. + +Events are not automatically disabled when the device file is closed. This must +be done manually, via a call to the ``SSAM_CDEV_EVENT_DISABLE`` IOCTL. + +``SSAM_CDEV_EVENT_DISABLE`` +--------------------------- + +Defined as ``_IOW(0xA5, 5, struct ssam_cdev_event_desc)``. + +Disable the event associated with the given event descriptor. + +Note that this will not unregister any notifiers. Events may still be received +and forwarded to user-space after this call. The only safe way of stopping +events from being received is unregistering all previously registered +notifiers. + + +Structures and Enums +==================== .. kernel-doc:: include/uapi/linux/surface_aggregator/cdev.h