From patchwork Fri Feb 14 15:35:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11382541 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CA1EF1580 for ; Fri, 14 Feb 2020 15:36:46 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 916EE2467B for ; Fri, 14 Feb 2020 15:36:46 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="kjMGsvsj" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 916EE2467B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=S+IVo1sgMM3nUvqpjeDNuM844dnWH0Ab5aI7NBI5ogM=; b=kjMGsvsjNY1aKym0F5nTKAh1wf u59QNQQLy51nPZBZKkwr9WFqXl5taA8/abuvuV06x0CTwGFAhJOVfHUiBIm28lC+eqRe63DGZ6Dm5 Cew/vPxsSehNS0oQLY0zD+Y7bYfyaQbcOhVT6xr1t+RRTVFrH4TBHywn7zqStWc/cBh4Pneu9z26r WuPlXjddzrqZe+VqOIzYZURi6fuvUGV4fwYh71Mr5Y0Gl5FHok4jL6gI0QoqR6W0j3ONW1TVD5ock hM7oeGNcsO36U/pPZih3OEppa2eOnRF35DpHWaV0QCXyE8KCj2aRxwJYdrBWfwd77RY+cm3Hf+Uv3 iuOpmobg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d1J-0001uL-IK; Fri, 14 Feb 2020 15:36:45 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d11-0001eL-60 for linux-arm-kernel@lists.infradead.org; Fri, 14 Feb 2020 15:36:28 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id BB126101E; Fri, 14 Feb 2020 07:36:26 -0800 (PST) Received: from e120937-lin.cambridge.arm.com (e120937-lin.cambridge.arm.com [10.1.197.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id BBFE83F68E; Fri, 14 Feb 2020 07:36:25 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 01/13] firmware: arm_scmi: Add receive buffer support for notifications Date: Fri, 14 Feb 2020 15:35:23 +0000 Message-Id: <20200214153535.32046-2-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200214153535.32046-1-cristian.marussi@arm.com> References: <20200214153535.32046-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200214_073627_308165_61027FCF X-CRM114-Status: GOOD ( 13.49 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.3 on bombadil.infradead.org summary: Content analysis details: (-2.3 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [217.140.110.172 listed in list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jonathan.Cameron@Huawei.com, cristian.marussi@arm.com, james.quinlan@broadcom.com, lukasz.luba@arm.com, sudeep.holla@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org From: Sudeep Holla With all the plumbing in place, let's just add the separate dedicated receive buffers to handle notifications that can arrive asynchronously from the platform firmware to OS. Also add one check to see if the platform supports any receive channels before allocating the receive buffers: since those buffers are optionally supported though, the whole xfer initialization is also postponed to be able to check for their existence in advance. Signed-off-by: Sudeep Holla [Changed parameters in __scmi_xfer_info_init()] Signed-off-by: Cristian Marussi --- V1 --> V2: - reviewed commit message - reviewed parameters of __scmi_xfer_info_init() --- drivers/firmware/arm_scmi/driver.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index dbec767222e9..efb660c34b57 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -76,6 +76,7 @@ struct scmi_xfers_info { * implementation version and (sub-)vendor identification. * @handle: Instance of SCMI handle to send to clients * @tx_minfo: Universal Transmit Message management info + * @rx_minfo: Universal Receive Message management info * @tx_idr: IDR object to map protocol id to Tx channel info pointer * @rx_idr: IDR object to map protocol id to Rx channel info pointer * @protocols_imp: List of protocols implemented, currently maximum of @@ -89,6 +90,7 @@ struct scmi_info { struct scmi_revision_info version; struct scmi_handle handle; struct scmi_xfers_info tx_minfo; + struct scmi_xfers_info rx_minfo; struct idr tx_idr; struct idr rx_idr; u8 *protocols_imp; @@ -525,13 +527,13 @@ int scmi_handle_put(const struct scmi_handle *handle) return 0; } -static int scmi_xfer_info_init(struct scmi_info *sinfo) +static int __scmi_xfer_info_init(struct scmi_info *sinfo, + struct scmi_xfers_info *info) { int i; struct scmi_xfer *xfer; struct device *dev = sinfo->dev; const struct scmi_desc *desc = sinfo->desc; - struct scmi_xfers_info *info = &sinfo->tx_minfo; /* Pre-allocated messages, no more than what hdr.seq can support */ if (WARN_ON(desc->max_msg >= MSG_TOKEN_MAX)) { @@ -566,6 +568,16 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo) return 0; } +static int scmi_xfer_info_init(struct scmi_info *sinfo) +{ + int ret = __scmi_xfer_info_init(sinfo, &sinfo->tx_minfo); + + if (!ret && idr_find(&sinfo->rx_idr, SCMI_PROTOCOL_BASE)) + ret = __scmi_xfer_info_init(sinfo, &sinfo->rx_minfo); + + return ret; +} + static int scmi_chan_setup(struct scmi_info *info, struct device *dev, int prot_id, bool tx) { @@ -699,10 +711,6 @@ static int scmi_probe(struct platform_device *pdev) info->desc = desc; INIT_LIST_HEAD(&info->node); - ret = scmi_xfer_info_init(info); - if (ret) - return ret; - platform_set_drvdata(pdev, info); idr_init(&info->tx_idr); idr_init(&info->rx_idr); @@ -715,6 +723,10 @@ static int scmi_probe(struct platform_device *pdev) if (ret) return ret; + ret = scmi_xfer_info_init(info); + if (ret) + return ret; + ret = scmi_base_protocol_init(handle); if (ret) { dev_err(dev, "unable to communicate with SCMI(%d)\n", ret); From patchwork Fri Feb 14 15:35:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11382543 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C693E1580 for ; Fri, 14 Feb 2020 15:37:12 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 993BE2467B for ; Fri, 14 Feb 2020 15:37:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="GRFG7l/S" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 993BE2467B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=E5a9Wy5GS7IS6F5xi/UbMqj/dxfqV7Lm5eYXgTeDYVI=; b=GRFG7l/SYEVbamRkE4uRGd5fDn N+FZytX6Q9Kju3FoJvpCSNasmAA3O1T9p3HnAymrydP3P+Wl3L7GvZu+ui1dpVZ6Q+R3TrL2Mg609 8/bJgFwC/HSFMf6t3N1ZpKXSZ70OUM6Jzvai+asuvFRaw+vz37cF+K2yMEwxCzBo6xBQLdu6mzR3X HSyFMFYBk2yrB3KFu10VxrDJad3xpPVqJ4QBcXjTOhF58ErSt2tVSPDOhD9RftrKcfunfJlPf3CA3 CQLqH61b0j6IH1EeFvcjNBPX0ohmxvRF7Pqx0+QhTBfj9e1gujvLdhA8X3ObjLmcf/ODsd71V4U3T z9zWzlyA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d1e-0002Bd-PU; Fri, 14 Feb 2020 15:37:06 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d12-0001fK-PI for linux-arm-kernel@lists.infradead.org; Fri, 14 Feb 2020 15:36:30 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id ED74D113E; Fri, 14 Feb 2020 07:36:27 -0800 (PST) Received: from e120937-lin.cambridge.arm.com (e120937-lin.cambridge.arm.com [10.1.197.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id EE90C3F68E; Fri, 14 Feb 2020 07:36:26 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 02/13] firmware: arm_scmi: Update protocol commands and notification list Date: Fri, 14 Feb 2020 15:35:24 +0000 Message-Id: <20200214153535.32046-3-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200214153535.32046-1-cristian.marussi@arm.com> References: <20200214153535.32046-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200214_073628_865965_1D646685 X-CRM114-Status: UNSURE ( 8.29 ) X-CRM114-Notice: Please train this message. X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.3 on bombadil.infradead.org summary: Content analysis details: (-2.3 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [217.140.110.172 listed in list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jonathan.Cameron@Huawei.com, cristian.marussi@arm.com, james.quinlan@broadcom.com, lukasz.luba@arm.com, sudeep.holla@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org From: Sudeep Holla Add commands' enumerations and messages definitions for all existing notify-enable commands across all protocols. Signed-off-by: Sudeep Holla Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/base.c | 7 +++++++ drivers/firmware/arm_scmi/perf.c | 5 +++++ drivers/firmware/arm_scmi/power.c | 6 ++++++ drivers/firmware/arm_scmi/sensors.c | 4 ++++ 4 files changed, 22 insertions(+) diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c index f804e8af6521..ce7d9203e41b 100644 --- a/drivers/firmware/arm_scmi/base.c +++ b/drivers/firmware/arm_scmi/base.c @@ -14,6 +14,13 @@ enum scmi_base_protocol_cmd { BASE_DISCOVER_LIST_PROTOCOLS = 0x6, BASE_DISCOVER_AGENT = 0x7, BASE_NOTIFY_ERRORS = 0x8, + BASE_SET_DEVICE_PERMISSIONS = 0x9, + BASE_SET_PROTOCOL_PERMISSIONS = 0xa, + BASE_RESET_AGENT_CONFIGURATION = 0xb, +}; + +enum scmi_base_protocol_notify { + BASE_ERROR_EVENT = 0x0, }; struct scmi_msg_resp_base_attributes { diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c index ec81e6f7e7a4..88509ec637d0 100644 --- a/drivers/firmware/arm_scmi/perf.c +++ b/drivers/firmware/arm_scmi/perf.c @@ -27,6 +27,11 @@ enum scmi_performance_protocol_cmd { PERF_DESCRIBE_FASTCHANNEL = 0xb, }; +enum scmi_performance_protocol_notify { + PERFORMANCE_LIMITS_CHANGED = 0x0, + PERFORMANCE_LEVEL_CHANGED = 0x1, +}; + struct scmi_opp { u32 perf; u32 power; diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c index 214886ce84f1..cf7f0312381b 100644 --- a/drivers/firmware/arm_scmi/power.c +++ b/drivers/firmware/arm_scmi/power.c @@ -12,6 +12,12 @@ enum scmi_power_protocol_cmd { POWER_STATE_SET = 0x4, POWER_STATE_GET = 0x5, POWER_STATE_NOTIFY = 0x6, + POWER_STATE_CHANGE_REQUESTED_NOTIFY = 0x7, +}; + +enum scmi_power_protocol_notify { + POWER_STATE_CHANGED = 0x0, + POWER_STATE_CHANGE_REQUESTED = 0x1, }; struct scmi_msg_resp_power_attributes { diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c index eba61b9c1f53..db1b1ab303da 100644 --- a/drivers/firmware/arm_scmi/sensors.c +++ b/drivers/firmware/arm_scmi/sensors.c @@ -14,6 +14,10 @@ enum scmi_sensor_protocol_cmd { SENSOR_READING_GET = 0x6, }; +enum scmi_sensor_protocol_notify { + SENSOR_TRIP_POINT_EVENT = 0x0, +}; + struct scmi_msg_resp_sensor_attributes { __le16 num_sensors; u8 max_requests; From patchwork Fri Feb 14 15:35:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11382545 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 21D7A13A4 for ; Fri, 14 Feb 2020 15:37:26 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id F04562467B for ; Fri, 14 Feb 2020 15:37:25 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="Z5NX23BY" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org F04562467B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=kFowjhkBvOcN8EZWg1o2HBgSLd30/qm/Yw2q7uSv0Y0=; b=Z5NX23BYX4IgFyWVF9znumu9Ad XoZn143qpdZG/gEFr5TBsNpnKFAIseFXVTZW4f5V4c81rHw+DwNZOzmb2Eoj46xo3LeqtVown2AcP 0NYmxt816Ap0PqyB06I2Wjsy/DCIpjiopDIVV+6LXik/dBE72Ku4+4POrAcaUIgnW+7Mh2d6339+y sm2HFAX2H4MBdU0eAzIaV7WDA7nvBy7qxZq4ii9Vb6uyfuZjDP9G/48kc+BU9EWCSy6/zv8NQ7eqc aSe/Ts+Ll5Y/7y4vsJzaDp7gygpnedTIsqFUjB59pm3Bz7Uc1rtywbVWGFSUQzpQgMnmjxLj3f7yf Qx8JeMkw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d1s-0002NL-AM; Fri, 14 Feb 2020 15:37:20 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d13-0001fo-Gs for linux-arm-kernel@lists.infradead.org; Fri, 14 Feb 2020 15:36:32 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 2CAA0106F; Fri, 14 Feb 2020 07:36:29 -0800 (PST) Received: from e120937-lin.cambridge.arm.com (e120937-lin.cambridge.arm.com [10.1.197.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 2CADC3F68E; Fri, 14 Feb 2020 07:36:28 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 03/13] firmware: arm_scmi: Add notifications support in transport layer Date: Fri, 14 Feb 2020 15:35:25 +0000 Message-Id: <20200214153535.32046-4-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200214153535.32046-1-cristian.marussi@arm.com> References: <20200214153535.32046-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200214_073629_662150_448DDF60 X-CRM114-Status: GOOD ( 11.55 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.3 on bombadil.infradead.org summary: Content analysis details: (-2.3 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [217.140.110.172 listed in list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jonathan.Cameron@Huawei.com, cristian.marussi@arm.com, james.quinlan@broadcom.com, lukasz.luba@arm.com, sudeep.holla@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Add common transport-layer methods to: - fetch a notification instead of a response - clear a pending notification Add also all the needed support in mailbox/shmem transports. Signed-off-by: Cristian Marussi Reviewed-by: Viresh Kumar --- drivers/firmware/arm_scmi/common.h | 8 ++++++++ drivers/firmware/arm_scmi/mailbox.c | 17 +++++++++++++++++ drivers/firmware/arm_scmi/shmem.c | 15 +++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 5ac06469b01c..3c2e5d0d7b68 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -178,6 +178,8 @@ struct scmi_chan_info { * @send_message: Callback to send a message * @mark_txdone: Callback to mark tx as done * @fetch_response: Callback to fetch response + * @fetch_notification: Callback to fetch notification + * @clear_notification: Callback to clear a pending notification * @poll_done: Callback to poll transfer status */ struct scmi_transport_ops { @@ -190,6 +192,9 @@ struct scmi_transport_ops { void (*mark_txdone)(struct scmi_chan_info *cinfo, int ret); void (*fetch_response)(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer); + void (*fetch_notification)(struct scmi_chan_info *cinfo, + size_t max_len, struct scmi_xfer *xfer); + void (*clear_notification)(struct scmi_chan_info *cinfo); bool (*poll_done)(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer); }; @@ -222,5 +227,8 @@ void shmem_tx_prepare(struct scmi_shared_mem __iomem *shmem, u32 shmem_read_header(struct scmi_shared_mem __iomem *shmem); void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem, struct scmi_xfer *xfer); +void shmem_fetch_notification(struct scmi_shared_mem __iomem *shmem, + size_t max_len, struct scmi_xfer *xfer); +void shmem_clear_notification(struct scmi_shared_mem __iomem *shmem); bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem, struct scmi_xfer *xfer); diff --git a/drivers/firmware/arm_scmi/mailbox.c b/drivers/firmware/arm_scmi/mailbox.c index 73077bbc4ad9..19ee058f9f44 100644 --- a/drivers/firmware/arm_scmi/mailbox.c +++ b/drivers/firmware/arm_scmi/mailbox.c @@ -158,6 +158,21 @@ static void mailbox_fetch_response(struct scmi_chan_info *cinfo, shmem_fetch_response(smbox->shmem, xfer); } +static void mailbox_fetch_notification(struct scmi_chan_info *cinfo, + size_t max_len, struct scmi_xfer *xfer) +{ + struct scmi_mailbox *smbox = cinfo->transport_info; + + shmem_fetch_notification(smbox->shmem, max_len, xfer); +} + +static void mailbox_clear_notification(struct scmi_chan_info *cinfo) +{ + struct scmi_mailbox *smbox = cinfo->transport_info; + + shmem_clear_notification(smbox->shmem); +} + static bool mailbox_poll_done(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer) { @@ -173,6 +188,8 @@ static struct scmi_transport_ops scmi_mailbox_ops = { .send_message = mailbox_send_message, .mark_txdone = mailbox_mark_txdone, .fetch_response = mailbox_fetch_response, + .fetch_notification = mailbox_fetch_notification, + .clear_notification = mailbox_clear_notification, .poll_done = mailbox_poll_done, }; diff --git a/drivers/firmware/arm_scmi/shmem.c b/drivers/firmware/arm_scmi/shmem.c index ca0ffd302ea2..e1ab05be90e3 100644 --- a/drivers/firmware/arm_scmi/shmem.c +++ b/drivers/firmware/arm_scmi/shmem.c @@ -67,6 +67,21 @@ void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem, memcpy_fromio(xfer->rx.buf, shmem->msg_payload + 4, xfer->rx.len); } +void shmem_fetch_notification(struct scmi_shared_mem __iomem *shmem, + size_t max_len, struct scmi_xfer *xfer) +{ + /* Skip only the length of header in shmem area i.e 4 bytes */ + xfer->rx.len = min_t(size_t, max_len, ioread32(&shmem->length) - 4); + + /* Take a copy to the rx buffer.. */ + memcpy_fromio(xfer->rx.buf, shmem->msg_payload, xfer->rx.len); +} + +void shmem_clear_notification(struct scmi_shared_mem __iomem *shmem) +{ + iowrite32(SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE, &shmem->channel_status); +} + bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem, struct scmi_xfer *xfer) { From patchwork Fri Feb 14 15:35:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11382547 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9957C13A4 for ; Fri, 14 Feb 2020 15:37:34 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7361C2467B for ; Fri, 14 Feb 2020 15:37:34 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="RN+avMFv" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7361C2467B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=y8yita2hSDEii/2p5lCM4iLYuaRnfjEGW5Il0lYY6bU=; b=RN+avMFvtl8bw9Yien3t3GXNMk CE9peXed2NAb0ZyVxg665knL7thOEp3BoJU+Krui8O4bLCxUQpwatc1LTk/YwXGG+eaZJJxnOMIBz zGqfF9oIHWC90yMXbcmWCuR2AKtvVmB9OjapbVLT8tOWwO3AvtYr21QRX8gs5UvLjL2hXtNYbNNbQ nb+ViHi4PgwiU+8QYcZ4KLRz6tbtEut7P1k21vVL/k+EEzebjzH9NagAt74M7h3+9LYJRbAFt/UfW p7t9zbhCTAa25ijphHl6Jmj34fH61E0jGvFbnBPmeu5Myaw/MKmK5aXhAfmi9eMsDj9lxflMbjMYh J6ZZ4r8w==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d21-0002Zj-9U; Fri, 14 Feb 2020 15:37:29 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d14-0001gx-Qd for linux-arm-kernel@lists.infradead.org; Fri, 14 Feb 2020 15:36:33 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 5F8F311D4; Fri, 14 Feb 2020 07:36:30 -0800 (PST) Received: from e120937-lin.cambridge.arm.com (e120937-lin.cambridge.arm.com [10.1.197.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 603CB3F68E; Fri, 14 Feb 2020 07:36:29 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 04/13] firmware: arm_scmi: Add support for notifications message processing Date: Fri, 14 Feb 2020 15:35:26 +0000 Message-Id: <20200214153535.32046-5-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200214153535.32046-1-cristian.marussi@arm.com> References: <20200214153535.32046-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200214_073630_990910_AFD82F3D X-CRM114-Status: GOOD ( 12.28 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.3 on bombadil.infradead.org summary: Content analysis details: (-2.3 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [217.140.110.172 listed in list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jonathan.Cameron@Huawei.com, cristian.marussi@arm.com, james.quinlan@broadcom.com, lukasz.luba@arm.com, sudeep.holla@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org From: Sudeep Holla Add the mechanisms to distinguish notifications from delayed responses and to properly fetch notification messages upon reception: notifications processing does not continue further after the fetch phase. Signed-off-by: Sudeep Holla [Reworked/renamed scmi_handle_xfer_delayed_resp()] Signed-off-by: Cristian Marussi --- V1 --> V2 - switch the notif/delayed_resp message processing logic to use new transport independent layer methods - reviewed logic of scmi_handle_xfer_delayed_resp() while renaming it as scmi_handle_response() - properly relocated tracer points --- drivers/firmware/arm_scmi/driver.c | 84 +++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 20 deletions(-) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index efb660c34b57..868cc36a07c9 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -202,29 +202,42 @@ __scmi_xfer_put(struct scmi_xfers_info *minfo, struct scmi_xfer *xfer) spin_unlock_irqrestore(&minfo->xfer_lock, flags); } -/** - * scmi_rx_callback() - callback for receiving messages - * - * @cinfo: SCMI channel info - * @msg_hdr: Message header - * - * Processes one received message to appropriate transfer information and - * signals completion of the transfer. - * - * NOTE: This function will be invoked in IRQ context, hence should be - * as optimal as possible. - */ -void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr) +static void scmi_handle_notification(struct scmi_chan_info *cinfo, u32 msg_hdr) { - struct scmi_info *info = handle_to_scmi_info(cinfo->handle); - struct scmi_xfers_info *minfo = &info->tx_minfo; - u16 xfer_id = MSG_XTRACT_TOKEN(msg_hdr); - u8 msg_type = MSG_XTRACT_TYPE(msg_hdr); - struct device *dev = cinfo->dev; struct scmi_xfer *xfer; + struct device *dev = cinfo->dev; + struct scmi_info *info = handle_to_scmi_info(cinfo->handle); + struct scmi_xfers_info *minfo = &info->rx_minfo; + + xfer = scmi_xfer_get(cinfo->handle, minfo); + if (IS_ERR(xfer)) { + dev_err(dev, "failed to get free message slot (%ld)\n", + PTR_ERR(xfer)); + info->desc->ops->clear_notification(cinfo); + return; + } + + unpack_scmi_header(msg_hdr, &xfer->hdr); + scmi_dump_header_dbg(dev, &xfer->hdr); + info->desc->ops->fetch_notification(cinfo, info->desc->max_msg_size, + xfer); + + trace_scmi_rx_done(xfer->transfer_id, xfer->hdr.id, + xfer->hdr.protocol_id, xfer->hdr.seq, + MSG_TYPE_NOTIFICATION); - if (msg_type == MSG_TYPE_NOTIFICATION) - return; /* Notifications not yet supported */ + __scmi_xfer_put(minfo, xfer); + + info->desc->ops->clear_notification(cinfo); +} + +static void scmi_handle_response(struct scmi_chan_info *cinfo, + u16 xfer_id, u8 msg_type) +{ + struct scmi_xfer *xfer; + struct device *dev = cinfo->dev; + struct scmi_info *info = handle_to_scmi_info(cinfo->handle); + struct scmi_xfers_info *minfo = &info->tx_minfo; /* Are we even expecting this? */ if (!test_bit(xfer_id, minfo->xfer_alloc_table)) { @@ -248,6 +261,37 @@ void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr) complete(&xfer->done); } +/** + * scmi_rx_callback() - callback for receiving messages + * + * @cinfo: SCMI channel info + * @msg_hdr: Message header + * + * Processes one received message to appropriate transfer information and + * signals completion of the transfer. + * + * NOTE: This function will be invoked in IRQ context, hence should be + * as optimal as possible. + */ +void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr) +{ + u16 xfer_id = MSG_XTRACT_TOKEN(msg_hdr); + u8 msg_type = MSG_XTRACT_TYPE(msg_hdr); + + switch (msg_type) { + case MSG_TYPE_NOTIFICATION: + scmi_handle_notification(cinfo, msg_hdr); + break; + case MSG_TYPE_COMMAND: + case MSG_TYPE_DELAYED_RESP: + scmi_handle_response(cinfo, xfer_id, msg_type); + break; + default: + WARN_ONCE(1, "received unknown msg_type:%d\n", msg_type); + break; + } +} + /** * scmi_xfer_put() - Release a transmit message * From patchwork Fri Feb 14 15:35:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11382549 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BF9F01580 for ; Fri, 14 Feb 2020 15:37:42 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 974642467B for ; Fri, 14 Feb 2020 15:37:42 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="rfBYg0vs" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 974642467B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=iPH3OSoxtgA78h3p70ZmW7weMzVS0gXnkjlH/WmoRxI=; b=rfBYg0vs8zPoztEbS7D5eVOs+F /iDSP75vq3H10RfaWusZ1/N7Pe3+oXEMXD8paPZH0hYaGOgmtUszskAQ59B2qt/bfo+ahV8D44lPr djOLtSJYYdLtukI6UgEKQDiHnMfbnRPdk0+uV7FBwxYkj344kNLaNOsl4eM04zwbIQu7h7QgdSGzF gU/r/hZiFslw04aMk6FFZgAtf6K1Jnnqohg/My/6Qb6gXnmJVGNTgJoPX7Z0yOW8oM4WD29QKMQ+P i+lx98c/L6lgPjhBD2jjIJvX/MhJ6ejVSp3LYpELqZZSNosvS4AOF6agg+00533Oetx0JIvcZkF5S zfQE+OHw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d2E-0002pk-1z; Fri, 14 Feb 2020 15:37:42 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d16-0001iN-7k for linux-arm-kernel@lists.infradead.org; Fri, 14 Feb 2020 15:36:35 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id ACEDB11FB; Fri, 14 Feb 2020 07:36:31 -0800 (PST) Received: from e120937-lin.cambridge.arm.com (e120937-lin.cambridge.arm.com [10.1.197.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 9365D3F68E; Fri, 14 Feb 2020 07:36:30 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 05/13] firmware: arm_scmi: Add notification protocol-registration Date: Fri, 14 Feb 2020 15:35:27 +0000 Message-Id: <20200214153535.32046-6-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200214153535.32046-1-cristian.marussi@arm.com> References: <20200214153535.32046-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200214_073632_478102_67170088 X-CRM114-Status: GOOD ( 22.56 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.3 on bombadil.infradead.org summary: Content analysis details: (-2.3 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [217.140.110.172 listed in list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jonathan.Cameron@Huawei.com, cristian.marussi@arm.com, james.quinlan@broadcom.com, lukasz.luba@arm.com, sudeep.holla@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Add core SCMI Notifications protocol-registration support: allow protocols to register their own set of supported events, during their initialization phase. Signed-off-by: Cristian Marussi --- V1 --> V2 - splitted out of V1 patch 04 - moved from IDR maps to real HashTables to store events - scmi_notifications_initialized is now an atomic_t - reviewed protocol registration/unregistration to use devres - fixed: drivers/firmware/arm_scmi/notify.c:483:18-23: ERROR: reference preceded by free on line 482 Reported-by: kbuild test robot Reported-by: Julia Lawall --- drivers/firmware/arm_scmi/Makefile | 2 +- drivers/firmware/arm_scmi/common.h | 4 + drivers/firmware/arm_scmi/notify.c | 425 +++++++++++++++++++++++++++++ drivers/firmware/arm_scmi/notify.h | 56 ++++ 4 files changed, 486 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/arm_scmi/notify.c create mode 100644 drivers/firmware/arm_scmi/notify.h diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile index 6694d0d908d6..24a03a36aee4 100644 --- a/drivers/firmware/arm_scmi/Makefile +++ b/drivers/firmware/arm_scmi/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only obj-y = scmi-bus.o scmi-driver.o scmi-protocols.o scmi-transport.o scmi-bus-y = bus.o -scmi-driver-y = driver.o +scmi-driver-y = driver.o notify.o scmi-transport-y = mailbox.o shmem.o scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 3c2e5d0d7b68..2106c35195ce 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -6,6 +6,8 @@ * * Copyright (C) 2018 ARM Ltd. */ +#ifndef _SCMI_COMMON_H +#define _SCMI_COMMON_H #include #include @@ -232,3 +234,5 @@ void shmem_fetch_notification(struct scmi_shared_mem __iomem *shmem, void shmem_clear_notification(struct scmi_shared_mem __iomem *shmem); bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem, struct scmi_xfer *xfer); + +#endif /* _SCMI_COMMON_H */ diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c new file mode 100644 index 000000000000..d496522dea72 --- /dev/null +++ b/drivers/firmware/arm_scmi/notify.c @@ -0,0 +1,425 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * System Control and Management Interface (SCMI) Notification support + * + * Copyright (C) 2019 ARM Ltd. + * + * SCMI Protocol specification allows the platform to signal events to + * interested agents via notification messages: this in an implementation + * of the dispatch and delivery of such notifications to the interested users + * inside the Linux kernel. + * + * Each SCMI Protocol implementation, during its initialization, registers with + * this core notification framework its set of supported events using + * @scmi_register_protocol_events(): all these protocols and events descriptors + * are stored in the @scmi_registered_protocols and @scmi_registered_events + * hashtables. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "notify.h" + +#define SCMI_ALL_SRC_IDS 0xffffUL + +/* + * Builds an unsigned 32bit key from the given input tuple to be used + * as a key in hashtables. + */ +#define MAKE_HASH_KEY(p, e, s) \ + ((u32)(((p) << 24) | ((e) << 16) | ((s) & SCMI_ALL_SRC_IDS))) + +/** + * Assumes that the stored obj includes its own hash-key in a field named 'key': + * with this simplification this macro can be equally used for all the objects' + * types hashed by this implementation. + * + * @__ht: The hashtable name + * @__obj: A pointer to the object type to be retrieved from the hashtable; + * it will be used as a cursor while scanning the hastable and it will + * be possibly left as NULL when @__k is not found + * @__k: The key to search for + */ +#define KEY_FIND(__ht, __obj, __k) \ +({ \ + hash_for_each_possible((__ht), (__obj), hash, (__k)) \ + if (likely((__obj)->key == (__k))) \ + break; \ + __obj; \ +}) + +/** + * events_queue - Describes a queue and its associated worker + * + * Each protocol has its own dedicated events_queue descriptor. + * + * @sz: Size in bytes of the related kfifo + * @qbuf: Pre-allocated buffer of @sz bytes to be used by the kfifo + * @kfifo: A dedicated Kernel kfifo + */ +struct events_queue { + size_t sz; + u8 *qbuf; + struct kfifo kfifo; +}; + +/** + * scmi_registered_protocol_events_desc - Protocol Specific information + * + * All protocols that registers at least one event have their protocol-specific + * information stored here, together with a ref to the allocated events_queue. + * These descriptors are stored in the @scmi_registered_protocols hashtable. + * + * @key: The used hashkey + * @id: Protocol ID + * @ops: Protocol specific and event-related operations + * @equeue: A reference to the associated per-protocol events_queue + * @hash: The hash list_node used for collision handling + * @gid: The associated devres group id, for cleanup purposes + */ +struct scmi_registered_protocol_events_desc { + u32 key; + u8 id; + const struct scmi_protocol_event_ops *ops; + struct events_queue *equeue; + struct hlist_node hash; + void *gid; +}; + +/** + * scmi_registered_event - Event Specific Information + * + * All registered events are represented by one of these structures. + * These descriptors are stored in the @scmi_registered_events hashtable. + * + * @key: The used hashkey + * @proto: A reference to the associated protocol descriptor + * @evt: A reference to the associated event descriptor (as provided at + * registration time) + * @scratch_isr: A pre-allocated buffer to be used as a scratch area by ISR + * @scratch_isr: A pre-allocated buffer to be used as a scratch area by the + * deferred worker + * @hash: The hash list_node used for collision handling + * @num_sources: The number of possible sources for this event as stated at + * events' registration time + * @sources: A reference to a dynamically allocated array used to refcount the + * events' enables for all the existing sources. + * @sources_mtx: A mutex to serialize the access to @sources + */ +struct scmi_registered_event { + u32 key; + struct scmi_registered_protocol_events_desc *proto; + const struct scmi_event *evt; + void *scratch_isr; + void *scratch_bh; + struct hlist_node hash; + u32 num_sources; + refcount_t *sources; + struct mutex sources_mtx; +}; + +/** + * scmi_event_header - A utility header + * + * This header is prepended to each received event message payload before + * queueing it on the related events_queue: it carries ancillary information + * for the attached event message payload. + * + * @timestamp: The timestamp, in nanoseconds (boottime), which was associated + * to this event as soon as it entered the SCMI RX ISR + * @proto_id: Protocol ID + * @evt_id: Event ID (corresponds to the Event MsgID for this Protocol) + * @payld_sz: Effective size of the attached message payload which follows + * @payld: A reference to the embedded event payload + */ +struct scmi_event_header { + u64 timestamp; + u8 proto_id; + u8 evt_id; + size_t payld_sz; + u8 payld[]; +} __packed; + +/* + * A few hashtables, of various size, to track: + * + * - @scmi_registered_protocols: All protocol-level specific information related + * to events' handling + * - @scmi_registered_events: All events' descriptors registered by the + * protocols, together with their ancillary data + */ +static DECLARE_HASHTABLE(scmi_registered_protocols, 4); +static DECLARE_HASHTABLE(scmi_registered_events, 5); + +static atomic_t scmi_notifications_initialized = ATOMIC_INIT(0); + +/** + * scmi_allocate_events_queue - Allocate/Initialize an events_queue descriptor + * + * Allocate an events_queue, a kfifo of the requested size and initialize the + * associated worker. + * + * @dev: Device to use for devres + * @sz: Size of the kfifo to initialize + * + * Return: A valid pointer to the allocated events_queue on Success + */ +static struct events_queue *scmi_allocate_events_queue(struct device *dev, + size_t sz) +{ + int ret; + struct events_queue *equeue; + + equeue = devm_kzalloc(dev, sizeof(*equeue), GFP_KERNEL); + if (!equeue) + return ERR_PTR(-ENOMEM); + + equeue->qbuf = devm_kzalloc(dev, sz, GFP_KERNEL); + if (!equeue->qbuf) + return ERR_PTR(-ENOMEM); + equeue->sz = sz; + + ret = kfifo_init(&equeue->kfifo, equeue->qbuf, equeue->sz); + if (ret) + return ERR_PTR(ret); + + return equeue; +} + +/** + * scmi_allocate_registered_protocol_desc - Allocate a registered protocol + * events' descriptor + * + * Used to keep protocol specific information related to events handling for any + * protocol which has registered at least one event. + * + * @dev: Device to use for devres + * @gid: Devres group id to be stored + * @proto_id: Protocol ID + * @queue_sz: Size of the associated queue to allocate + * @ops: Pointer to a struct holding references to protocol specific helpers + * needed during events handling + */ +static struct scmi_registered_protocol_events_desc * +scmi_allocate_registered_protocol_desc(struct device *dev, void *gid, + u8 proto_id, size_t queue_sz, + const struct scmi_protocol_event_ops *ops) +{ + struct scmi_registered_protocol_events_desc *pdesc; + u32 proto_key = MAKE_HASH_KEY(proto_id, 0, SCMI_ALL_SRC_IDS); + + pdesc = KEY_FIND(scmi_registered_protocols, pdesc, proto_key); + if (pdesc) + return pdesc; + + pdesc = devm_kzalloc(dev, sizeof(*pdesc), GFP_KERNEL); + if (!pdesc) + return ERR_PTR(-ENOMEM); + pdesc->key = proto_key; + pdesc->id = proto_id; + pdesc->ops = ops; + pdesc->gid = gid; + + pdesc->equeue = scmi_allocate_events_queue(dev, queue_sz); + if (IS_ERR(pdesc->equeue)) + return ERR_PTR(PTR_ERR(pdesc->equeue)); + + hash_add(scmi_registered_protocols, &pdesc->hash, pdesc->key); + + return pdesc; +} + +/** + * scmi_register_protocol_events - Register Protocol Events with the core + * + * Used by SCMI Protocols initialization code to register with the notification + * core the list of supported events and their descriptors: takes care to + * pre-allocate amd store all needed descriptors, scratch buffers and event + * queues. + * + * @dev: Device to use for devres + * @proto_id: Protocol ID + * @queue_sz: Size in bytes of the associated queue to be allocated + * @ops: Protocol specific event-related operations + * @evt: Event descriptor array + * @num_events: Number of events in @evt array + * @num_sources: Number of possible sources for this protocol on this + * platform. + * + * Return: 0 on Success + */ +int scmi_register_protocol_events(struct device *dev, + u8 proto_id, size_t queue_sz, + const struct scmi_protocol_event_ops *ops, + const struct scmi_event *evt, int num_events, + int num_sources) +{ + int i; + void *gid; + struct scmi_registered_protocol_events_desc *pdesc; + + /* Ensure atomic value is updated */ + smp_mb__before_atomic(); + if (!ops || !evt || + unlikely(!atomic_read(&scmi_notifications_initialized))) + return -EINVAL; + + gid = devres_open_group(dev, NULL, GFP_KERNEL); + if (!gid) + return -ENOMEM; + + pdesc = scmi_allocate_registered_protocol_desc(dev, gid, proto_id, + queue_sz, ops); + if (IS_ERR(pdesc)) + goto err; + + for (i = 0; i < num_events; i++, evt++) { + struct scmi_registered_event *r_evt; + + r_evt = devm_kzalloc(dev, sizeof(*r_evt), GFP_KERNEL); + if (!r_evt) + goto err; + r_evt->proto = pdesc; + r_evt->evt = evt; + + r_evt->sources = devm_kcalloc(dev, num_sources, + sizeof(refcount_t), GFP_KERNEL); + if (!r_evt->sources) + goto err; + r_evt->num_sources = num_sources; + mutex_init(&r_evt->sources_mtx); + + r_evt->scratch_isr = devm_kzalloc(dev, + sizeof(struct scmi_event_header) + + evt->max_payld_sz, GFP_KERNEL); + if (!r_evt->scratch_isr) + goto err; + + r_evt->scratch_bh = devm_kzalloc(dev, evt->max_payld_sz, + GFP_KERNEL); + if (!r_evt->scratch_bh) + goto err; + + r_evt->key = MAKE_HASH_KEY(r_evt->proto->id, + r_evt->evt->evt_id, + SCMI_ALL_SRC_IDS); + hash_add(scmi_registered_events, &r_evt->hash, r_evt->key); + + pr_info("SCMI Notifications: registered event - key:%X\n", + r_evt->key); + } + devres_close_group(dev, NULL); + + return 0; + +err: + pr_warn("SCMI Notifications - Proto:%X - Registration Failed !\n", + proto_id); + devres_release_group(dev, NULL); + return -ENOMEM; +} + +/** + * scmi_unregister_protocol_events - Unregister protocol-event resources + * + * Removes all registered events related to this protocol descriptor and + * frees all the underlying resources associated with this protocol devres + * group id. + * + * Assumes that the caller has already taken care to stop events dispatching + * and to flush the related queue. (via scmi_stop_and_flush_protocol_events) + * + * @dev: Device to use for devres + * @proto_id: The protocol to act upon + * + * Return: The number of released non-group resources + */ +int scmi_unregister_protocol_events(struct device *dev, u8 proto_id) +{ + int bkt; + struct scmi_registered_event *r_evt; + struct scmi_registered_protocol_events_desc *pdesc; + + pdesc = KEY_FIND(scmi_registered_protocols, pdesc, + MAKE_HASH_KEY(proto_id, 0, SCMI_ALL_SRC_IDS)); + if (!pdesc) + return 0; + + /* Remove all registered events for pdesc and pdesc itself */ + hash_for_each(scmi_registered_events, bkt, r_evt, hash) + if (r_evt->proto == pdesc) + hash_del(&r_evt->hash); + hash_del(&pdesc->hash); + + /* Free all underlying resources */ + return devres_release_group(dev, pdesc->gid); +} + +/** + * scmi_stop_and_flush_protocol_events - Stop events processing + * + * Stop ISR dispatching and flush protocol queue: after this point no more + * events will be queued for this protocol and so, most importantly lookups + * on scmi_registered_events cannot happen anymore. + * Note that here we want to address also the possibility that a faulty + * platform keeps on emitting notification message even after having being + * asked to stop after the last user has gone. + * + * @proto_id: The protocol to act upon + * + * Return: False if protocol not found, True otherwise + */ +bool scmi_stop_and_flush_protocol_events(u8 proto_id) +{ + struct scmi_registered_protocol_events_desc *pdesc; + + pdesc = KEY_FIND(scmi_registered_protocols, pdesc, + MAKE_HASH_KEY(proto_id, 0, SCMI_ALL_SRC_IDS)); + if (!pdesc) + return false; + + atomic_set(&scmi_notifications_initialized, 0); + /* Ensure atomic value is updated */ + smp_mb__after_atomic(); + + return true; +} + +/** + * scmi_notification_init - Initializes Notification Core Support + * + * Return: 0 on Success + */ +int __init scmi_notification_init(void) +{ + hash_init(scmi_registered_protocols); + hash_init(scmi_registered_events); + + atomic_set(&scmi_notifications_initialized, 1); + /* Ensure atomic value is updated */ + smp_mb__after_atomic(); + + pr_info("SCMI Notifications Core enabled.\n"); + + return 0; +} + +/** + * scmi_notification_exit - Shutdown and clean Notification core + */ +void __exit scmi_notification_exit(void) +{ + pr_info("SCMI Notifications Core disabled.\n"); +} diff --git a/drivers/firmware/arm_scmi/notify.h b/drivers/firmware/arm_scmi/notify.h new file mode 100644 index 000000000000..3f8a69c85a36 --- /dev/null +++ b/drivers/firmware/arm_scmi/notify.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * System Control and Management Interface (SCMI) Message Protocol + * notification header file containing some definitions, structures + * and function prototypes related to SCMI Notification handling. + * + * Copyright (C) 2019 ARM Ltd. + */ +#ifndef _SCMI_NOTIFY_H +#define _SCMI_NOTIFY_H + +#include +#include + +/** + * scmi_event - Describes an event to be supported + * + * Each SCMI protocol, during its initialization phase, can describe the events + * it wishes to support in a few struct scmi_event and pass them to the core + * using scmi_register_protocol_events(). + * + * @evt_id: Event ID + * @max_payld_sz: Max possible size for the payload of a notif msg of this kind + * @max_report_sz: Max possible size for the report of a notif msg of this kind + */ +struct scmi_event { + u8 evt_id; + size_t max_payld_sz; + +}; + +/** + * scmi_protocol_event_ops - Helpers called by notification core. + * + * These are called only in process context. + * + * @set_notify_enabled: Enable/disable the required evt_id/src_id notifications + * using the proper custom protocol commands. + * Return true if at least one the required src_id + * has been successfully enabled/disabled + */ +struct scmi_protocol_event_ops { + bool (*set_notify_enabled)(u8 evt_id, u32 src_id, bool enabled); +}; + +int scmi_notification_init(void); +void scmi_notification_exit(void); +int scmi_register_protocol_events(struct device *dev, + u8 proto_id, size_t queue_sz, + const struct scmi_protocol_event_ops *ops, + const struct scmi_event *evt, int num_events, + int num_sources); +int scmi_unregister_protocol_events(struct device *dev, u8 proto_id); +bool scmi_stop_and_flush_protocol_events(u8 proto_id); + +#endif /* _SCMI_NOTIFY_H */ From patchwork Fri Feb 14 15:35:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11382551 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C3A061580 for ; Fri, 14 Feb 2020 15:37:58 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9E30E2467B for ; Fri, 14 Feb 2020 15:37:58 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="fFJDc9nd" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 9E30E2467B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=1UX71DAuMKb1P2AFihvUdtyhhGenIx/nUCk/1CG1sQc=; b=fFJDc9ndICtYIdTStGZvvxZqH+ dGZGMhdx2815Yy/ruOTDk4QLirbX6Z9CCDlIVFJRaEwnRNqthJornocVXKlSc+VJ3jQLPoIjthOwI N154w/Z+nIt0bO3wyCTOv2k1jYTEdBq8CccCG/SX1/utFPMNiNoSB4g6nFOKjzIkyyeYpTbqUn9j+ wWfCXOiStem9UumeIwLjzHeQToBdOr1G1mIarQyfJoMPcDK1ZdTgOjf/K9VbntBEurqlX2omYPCIe 1YbdlFjPb6WVEHl9I1NfEt9HoSprjv2M0pCl9BoBqIUsEuEJ96PWOBl+G2wRb41MoULRYQsM5BgaX /lHxOJ9A==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d2N-00030N-8L; Fri, 14 Feb 2020 15:37:51 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d17-0001fo-9a for linux-arm-kernel@lists.infradead.org; Fri, 14 Feb 2020 15:36:37 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 0695F328; Fri, 14 Feb 2020 07:36:33 -0800 (PST) Received: from e120937-lin.cambridge.arm.com (e120937-lin.cambridge.arm.com [10.1.197.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id E0C333F68E; Fri, 14 Feb 2020 07:36:31 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 06/13] firmware: arm_scmi: Add notification callbacks-registration Date: Fri, 14 Feb 2020 15:35:28 +0000 Message-Id: <20200214153535.32046-7-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200214153535.32046-1-cristian.marussi@arm.com> References: <20200214153535.32046-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200214_073633_481989_63FF761B X-CRM114-Status: GOOD ( 25.13 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.3 on bombadil.infradead.org summary: Content analysis details: (-2.3 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [217.140.110.172 listed in list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jonathan.Cameron@Huawei.com, cristian.marussi@arm.com, james.quinlan@broadcom.com, lukasz.luba@arm.com, sudeep.holla@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Add core SCMI Notifications callbacks-registration support: allow users to register their own callbacks against the desired events. Signed-off-by: Cristian Marussi --- V1 --> V2 - splitted out of V1 patch 04 - moved from IDR maps to real HashTables to store event_handlers - added proper enable_events refcounting via __scmi_enable_evt() [was broken in V1 when using ALL_SRCIDs notification chains] - reviewed hashtable cleanup strategy in scmi_notifications_exit() - added scmi_register_event_notifier()/scmi_unregister_event_notifier() to include/linux/scmi_protocol.h as a candidate user API [no EXPORTs still] - added notify_ops to handle during initialization as an additional internal API for scmi_drivers --- drivers/firmware/arm_scmi/notify.c | 443 ++++++++++++++++++++++++++++- drivers/firmware/arm_scmi/notify.h | 2 +- include/linux/scmi_protocol.h | 63 ++++ 3 files changed, 505 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c index d496522dea72..1339b6de0a4c 100644 --- a/drivers/firmware/arm_scmi/notify.c +++ b/drivers/firmware/arm_scmi/notify.c @@ -14,18 +14,56 @@ * @scmi_register_protocol_events(): all these protocols and events descriptors * are stored in the @scmi_registered_protocols and @scmi_registered_events * hashtables. + * + * Kernel users interested in some specific event can register their associated + * callbacks providing the usual notifier_block descriptor, since this + * notification system implements events' delivery using the standard Kernel + * notification chains machinery. All users provided callbacks are instead + * stored in the @scmi_registered_events_handlers hashtable. + * + * Given the number of possible events defined by SCMI and the extensibility + * of the SCMI Protocol itself, the underlying notification chains are created + * and destroyed dynamically on demand depending on the number of users + * effectively registered for an event, so that no support structures or chains + * are allocated until at least one user has registered a notifier_block for + * such event. Similarly, events' generation itself is enabled at the platform + * level only after at least one user has registered, and it is shutdown after + * the last user for that event has gone. + * + * An event is identified univocally by the tuple (proto_id, evt_id, src_id) + * and is served by its own dedicated notification chain: given that such chain + * is indeed dynamically created, the registration API simply represents a mean + * for the users to associate their callbacks with the above tuple descriptor + * and possibly trigger the allocation and initialization of all the required + * resources. + * + * The information contained in such tuples is used, in a few different ways, + * to generate the final keys used to store/retrieve descriptors from the above + * hastables. + * + * Here proto_id and evt_id are simply the protocol_id and message_id numbers + * as described in the SCMI Protocol specification, while src_id represents an + * optional, protocol dependent, source identifier (like domain_id, perf_id + * or sensor_id and so forth), so that a user can register its callback for a + * particular event coming only from a well defined source (like CPU vs GPU). + * When the source is not specified the user callback will be registered for + * all existing sources for that event (if any). */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include +#include #include #include #include #include +#include #include +#include #include +#include #include #include #include @@ -60,6 +98,17 @@ __obj; \ }) +#define PROTO_ID_MASK GENMASK(31, 24) +#define EVT_ID_MASK GENMASK(23, 16) +#define SRC_ID_MASK GENMASK(15, 0) +#define KEY_XTRACT_PROTO_ID(key) FIELD_GET(PROTO_ID_MASK, (key)) +#define KEY_XTRACT_EVT_ID(key) FIELD_GET(EVT_ID_MASK, (key)) +#define KEY_XTRACT_SRC_ID(key) FIELD_GET(SRC_ID_MASK, (key)) + +/* A couple of utility macros to limit cruft when calling protocols' helpers */ +#define REVT_NOTIFY_ENABLE(revt, ...) \ + ((revt)->proto->ops->set_notify_enabled(__VA_ARGS__)) + /** * events_queue - Describes a queue and its associated worker * @@ -130,6 +179,32 @@ struct scmi_registered_event { struct mutex sources_mtx; }; +/** + * scmi_event_handler - Event handler information + * + * This structure collects all the information needed to process a received + * event described by the tuple (proto_id, evt_id, src_id) invoking all the + * currently registered users' callbacks. + * These descriptors are stored in the @scmi_registered_events_handlers + * hashtable using as a key a value derived from that tuple. + * + * @key: The used hashkey + * @users: A reference count for number of active users for this handler + * @r_evt: A reference to the underlying registered event + * @chain: The notification chain dedicated to this specific event tuple + * @hash: The hash list_node used for collision handling + * @enabled: A boolean which records if event's generation has been already + * enabled for this handler as a whole + */ +struct scmi_event_handler { + u32 key; + refcount_t users; + struct scmi_registered_event *r_evt; + struct blocking_notifier_head chain; + struct hlist_node hash; + bool enabled; +}; + /** * scmi_event_header - A utility header * @@ -159,9 +234,22 @@ struct scmi_event_header { * to events' handling * - @scmi_registered_events: All events' descriptors registered by the * protocols, together with their ancillary data + * - @scmi_registered_events_handlers: All events' handlers descriptors, created + * to collect all the users' notifier_block + * callbacks and related notification chains */ static DECLARE_HASHTABLE(scmi_registered_protocols, 4); static DECLARE_HASHTABLE(scmi_registered_events, 5); +static DECLARE_HASHTABLE(scmi_registered_events_handlers, 8); + +/* + * A mutex to coordinate access to @scmi_registered_events_handlers which is the + * only hashtable which can potentially have multiple concurrent readers and + * writers at run-time; all other hashtables are fully populated at init time + * and then subsequently only read till cleanup-time when all notifications' + * processing would have been anyway already being stopped. + */ +static DEFINE_MUTEX(scmi_registered_events_handler_mtx); static atomic_t scmi_notifications_initialized = ATOMIC_INIT(0); @@ -352,6 +440,18 @@ int scmi_unregister_protocol_events(struct device *dev, u8 proto_id) struct scmi_registered_event *r_evt; struct scmi_registered_protocol_events_desc *pdesc; + /* + * We should get here only after all users have unregistered their + * handlers using the API...if that's not the case give up. + */ + mutex_lock(&scmi_registered_events_handler_mtx); + if (!hash_empty(scmi_registered_events_handlers)) { + pr_err("SCMI Notifications: active users found at exit.\n"); + mutex_unlock(&scmi_registered_events_handler_mtx); + return 0; + } + mutex_unlock(&scmi_registered_events_handler_mtx); + pdesc = KEY_FIND(scmi_registered_protocols, pdesc, MAKE_HASH_KEY(proto_id, 0, SCMI_ALL_SRC_IDS)); if (!pdesc) @@ -397,15 +497,354 @@ bool scmi_stop_and_flush_protocol_events(u8 proto_id) return true; } +/** + * scmi_allocate_event_handler - Allocate and Register an Event handler + * + * Allocate an event handler and related notification chain associated with + * the event identified by the provided event key. Fails if the associated + * event is unknown to the core (i.e. it had not been previously registered + * as supported by some SCMI protocol) + * + * @evt_key: 32bit key uniquely bind to the event identified by the tuple + * (proto_id, evt_id, src_id) + * + * Return: the freshly allocated structure on Success + */ +static struct scmi_event_handler *scmi_allocate_event_handler(u32 evt_key) +{ + u8 proto_id, evt_id; + struct scmi_registered_event *r_evt; + struct scmi_event_handler *hndl; + + proto_id = KEY_XTRACT_PROTO_ID(evt_key); + evt_id = KEY_XTRACT_EVT_ID(evt_key); + r_evt = KEY_FIND(scmi_registered_events, r_evt, + MAKE_HASH_KEY(proto_id, evt_id, SCMI_ALL_SRC_IDS)); + if (!r_evt) + return ERR_PTR(-EINVAL); + + hndl = kzalloc(sizeof(*hndl), GFP_KERNEL); + if (!hndl) + return ERR_PTR(-ENOMEM); + hndl->r_evt = r_evt; + hndl->key = evt_key; + BLOCKING_INIT_NOTIFIER_HEAD(&hndl->chain); + refcount_set(&hndl->users, 1); + + /* Register freshly allocated event handler */ + hash_add(scmi_registered_events_handlers, &hndl->hash, hndl->key); + + return hndl; +} + +/** + * scmi_free_event_handler - Free the provided Event handler + * + * @hndl: The event handler structure to free + */ +static void scmi_free_event_handler(struct scmi_event_handler *hndl) +{ + hash_del(&hndl->hash); + kfree(hndl); +} + +/** + * __scmi_event_handler_get_ops - Utility to get or create an event handler + * + * After having got exclusive access to the registered events hashtable, + * search for the desired handler matching the key: + * - if found adjust users refcount + * - if not found and @create is true, create and register a new handler + * + * Events generation is NOT enabled on create within this routine since at + * creation time we usually want to have all setup and registered before events + * really start flowing. + * + * @evt_key: The event key to use + * @create: A boolean flag to specify if a handler must be created when + * not already existent + * + * Return: the freshly allocated structure on Success + */ +static inline struct scmi_event_handler * +__scmi_event_handler_get_ops(u32 evt_key, bool create) +{ + struct scmi_event_handler *hndl = NULL; + + mutex_lock(&scmi_registered_events_handler_mtx); + hndl = KEY_FIND(scmi_registered_events_handlers, hndl, evt_key); + if (hndl) + refcount_inc(&hndl->users); + else if (create) + hndl = scmi_allocate_event_handler(evt_key); + mutex_unlock(&scmi_registered_events_handler_mtx); + + return hndl; +} + +static struct scmi_event_handler *scmi_get_event_handler(u32 evt_key) +{ + return __scmi_event_handler_get_ops(evt_key, false); +} + +static struct scmi_event_handler *scmi_get_or_create_event_handler(u32 evt_key) +{ + return __scmi_event_handler_get_ops(evt_key, true); +} + +/** + * __scmi_enable_evt - Enable/disable events generation + * + * Takes care of proper refcounting while performing enable/disable: + * handles the special case of ALL sources requests. + * + * @r_evt: The registered event to act upon + * @src_id: The src_id to act upon + * @enable: The action to perform: true->Enable, false->Disable + * + * Return: True when the required @action has been successfully executed + */ +static inline bool __scmi_enable_evt(struct scmi_registered_event *r_evt, + u32 src_id, bool enable) +{ + int ret = 0; + u32 num_sources; + refcount_t *sid; + + if (src_id == SCMI_ALL_SRC_IDS) { + src_id = 0; + num_sources = r_evt->num_sources; + } else if (src_id < r_evt->num_sources) { + num_sources = 1; + } else { + return ret; + } + + mutex_lock(&r_evt->sources_mtx); + if (enable) { + for (; num_sources; src_id++, num_sources--) { + bool r; + + sid = &r_evt->sources[src_id]; + if (refcount_read(sid) == 0) { + r = REVT_NOTIFY_ENABLE(r_evt, + r_evt->evt->evt_id, + src_id, enable); + if (r) + refcount_set(sid, 1); + } else { + refcount_inc(sid); + r = true; + } + ret += r; + } + } else { + for (; num_sources; src_id++, num_sources--) { + sid = &r_evt->sources[src_id]; + if (refcount_dec_and_test(sid)) + REVT_NOTIFY_ENABLE(r_evt, + r_evt->evt->evt_id, + src_id, enable); + } + ret = 1; + } + mutex_unlock(&r_evt->sources_mtx); + + return ret; +} + +static bool scmi_enable_events(struct scmi_event_handler *hndl) +{ + if (!hndl->enabled) + hndl->enabled = __scmi_enable_evt(hndl->r_evt, + KEY_XTRACT_SRC_ID(hndl->key), + true); + return hndl->enabled; +} + +static bool scmi_disable_events(struct scmi_event_handler *hndl) +{ + if (hndl->enabled) + hndl->enabled = !__scmi_enable_evt(hndl->r_evt, + KEY_XTRACT_SRC_ID(hndl->key), + false); + return !hndl->enabled; +} + +static inline +void scmi_put_event_handler_unlocked(struct scmi_event_handler *hndl) +{ + if (refcount_dec_and_test(&hndl->users)) { + scmi_disable_events(hndl); + scmi_free_event_handler(hndl); + } +} + +/** + * scmi_put_event_handler - Put an event handler + * + * After having got exclusive access to the registered events hashtable, update + * the refcount and if @hndl is no more in use by anyone: + * + * - ask for events' generation disabling + * - unregister and free the handler itself + * + * @hndl: The handler to act upon + */ +static void scmi_put_event_handler(struct scmi_event_handler *hndl) +{ + mutex_lock(&scmi_registered_events_handler_mtx); + scmi_put_event_handler_unlocked(hndl); + mutex_unlock(&scmi_registered_events_handler_mtx); +} + +static int scmi_register_notifier(u8 proto_id, u8 evt_id, u32 *src_id, + struct notifier_block *nb) +{ + u32 evt_key; + struct scmi_event_handler *hndl; + + /* Ensure atomic value is updated */ + smp_mb__before_atomic(); + if (unlikely(!atomic_read(&scmi_notifications_initialized))) + return 0; + + /* Account for handle->notify_ops access */ + try_module_get(THIS_MODULE); + + evt_key = MAKE_HASH_KEY(proto_id, evt_id, + src_id ? *src_id : SCMI_ALL_SRC_IDS); + hndl = scmi_get_or_create_event_handler(evt_key); + if (IS_ERR_OR_NULL(hndl)) + return PTR_ERR(hndl); + + blocking_notifier_chain_register(&hndl->chain, nb); + + /* + * Ask platform to enable events': effective requests are emitted + * only when required by the current state of the underlying sources. + */ + if (!scmi_enable_events(hndl)) { + pr_err("SCMI Notifications: Failed to ENABLE events for key:%X !\n", + evt_key); + blocking_notifier_chain_unregister(&hndl->chain, nb); + scmi_put_event_handler(hndl); + return -EINVAL; + } + + return 0; +} + +/** + * scmi_register_event_notifier - Register a notifier_block for an event + * + * Generic helper to register a notifier_block attached to a protocol event. + * + * A notifier_block @nb will be registered for each distinct event identified + * by the tuple (proto_id, evt_id, src_id) on a dedicated notification chain + * so that: + * + * (proto_X, evt_Y, src_Z) --> chain_X_Y_Z + * + * @src_id meaning is protocol specific and identifies the origin of the event + * (like domain_id, sensor_id and os forth). + * + * @src_id can be NULL to signify that the caller is interested in receiving + * notifications from ALL the available sources for that protocol OR simply that + * the protocol does not support distinct sources: in these cases @nb will be + * attached to a generic notification chain defined for ALL src_id of that + * proto_id/evt_id pair like: + * + * (proto_X, evt_Y, NULL) --> chain_X_Y_ALL + * + * Any received event will be then dispatched to both such chains if at least + * one user had registered an @nb on them. + * + * @proto_id: Protocol ID + * @evt_id: Event ID + * @src_id: Source ID, when NULL register for events coming form ALL possible + * sources + * @nb: A standard notifier block to register for the specified event + * + * Return: Return 0 on Success + */ +int scmi_register_event_notifier(u8 proto_id, u8 evt_id, u32 *src_id, + struct notifier_block *nb) +{ + return scmi_register_notifier(proto_id, evt_id, src_id, nb); +} + +static int scmi_unregister_notifier(u8 proto_id, u8 evt_id, u32 *src_id, + struct notifier_block *nb) +{ + u32 evt_key; + struct scmi_event_handler *hndl; + + /* Account for handle->notify_ops access */ + module_put(THIS_MODULE); + + evt_key = MAKE_HASH_KEY(proto_id, evt_id, + src_id ? *src_id : SCMI_ALL_SRC_IDS); + hndl = scmi_get_event_handler(evt_key); + if (IS_ERR_OR_NULL(hndl)) + return -EINVAL; + + blocking_notifier_chain_unregister(&hndl->chain, nb); + scmi_put_event_handler(hndl); + /* + * If this was the last user callback for this handler, this last + * additional put will force the handler to be freed. + * Note that if a call_chain walk is ongoing it will be instead the + * call_chain's put_request which will finally free the handler; + * note also that any operation on the inner notifier_block chain + * is already protected on its own. + */ + scmi_put_event_handler(hndl); + + return 0; +} + +/** + * scmi_unregister_event_notifier - Unregister a notifier_block for an event + * + * Takes care to unregister the provided @nb from the notification chain + * associated to the specified event and, if there are no more users for the + * event handler, frees also the associated event handler structures. + * + * @proto_id: Protocol ID + * @evt_id: Event ID + * @src_id: Source ID + * @nb: The notifier_block to unregister + * + * Return: 0 on Success + */ +int scmi_unregister_event_notifier(u8 proto_id, u8 evt_id, u32 *src_id, + struct notifier_block *nb) +{ + return scmi_unregister_notifier(proto_id, evt_id, src_id, nb); +} + +/* + * notify_ops are also to the attached to the handle so that can be accessed + * directly from an scmi_driver to register its own notifiers. + */ +static struct scmi_notify_ops notify_ops = { + .register_event_notifier = scmi_register_notifier, + .unregister_event_notifier = scmi_unregister_notifier, +}; + /** * scmi_notification_init - Initializes Notification Core Support * * Return: 0 on Success */ -int __init scmi_notification_init(void) +int scmi_notification_init(struct scmi_handle *handle) { hash_init(scmi_registered_protocols); hash_init(scmi_registered_events); + hash_init(scmi_registered_events_handlers); + + handle->notify_ops = ¬ify_ops; atomic_set(&scmi_notifications_initialized, 1); /* Ensure atomic value is updated */ @@ -419,7 +858,7 @@ int __init scmi_notification_init(void) /** * scmi_notification_exit - Shutdown and clean Notification core */ -void __exit scmi_notification_exit(void) +void scmi_notification_exit(void) { pr_info("SCMI Notifications Core disabled.\n"); } diff --git a/drivers/firmware/arm_scmi/notify.h b/drivers/firmware/arm_scmi/notify.h index 3f8a69c85a36..438181147fc8 100644 --- a/drivers/firmware/arm_scmi/notify.h +++ b/drivers/firmware/arm_scmi/notify.h @@ -43,7 +43,7 @@ struct scmi_protocol_event_ops { bool (*set_notify_enabled)(u8 evt_id, u32 src_id, bool enabled); }; -int scmi_notification_init(void); +int scmi_notification_init(struct scmi_handle *handle); void scmi_notification_exit(void); int scmi_register_protocol_events(struct device *dev, u8 proto_id, size_t queue_sz, diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 5c873a59b387..f675f2aa7d87 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -4,7 +4,12 @@ * * Copyright (C) 2018 ARM Ltd. */ + +#ifndef _LINUX_SCMI_PROTOCOL_H +#define _LINUX_SCMI_PROTOCOL_H + #include +#include #include #define SCMI_MAX_STR_SIZE 16 @@ -207,6 +212,24 @@ struct scmi_reset_ops { int (*deassert)(const struct scmi_handle *handle, u32 domain); }; +/** + * scmi_notify_ops - represents notifications' operations provided by SCMI core + * + * Further details below within documentation for @scmi_register_event_notifier + * and @scmi_unregister_event_notifier(). The functionality is the same, they + * are just exposed in a different way. + * + * @register_event_notifier: Register a notifier_block for the requested event + * @unregister_event_notifier: Unregister a notifier_block for the requested + * event + */ +struct scmi_notify_ops { + int (*register_event_notifier)(u8 proto_id, u8 evt_id, u32 *src_id, + struct notifier_block *nb); + int (*unregister_event_notifier)(u8 proto_id, u8 evt_id, u32 *src_id, + struct notifier_block *nb); +}; + /** * struct scmi_handle - Handle returned to ARM SCMI clients for usage. * @@ -236,6 +259,7 @@ struct scmi_handle { struct scmi_power_ops *power_ops; struct scmi_sensor_ops *sensor_ops; struct scmi_reset_ops *reset_ops; + struct scmi_notify_ops *notify_ops; /* for protocol internal use */ void *perf_priv; void *clk_priv; @@ -319,3 +343,42 @@ static inline void scmi_driver_unregister(struct scmi_driver *driver) {} typedef int (*scmi_prot_init_fn_t)(struct scmi_handle *); int scmi_protocol_register(int protocol_id, scmi_prot_init_fn_t fn); void scmi_protocol_unregister(int protocol_id); + +/* + * SCMI Notification User API + * + * A user can register/unregister its own notifier_block against the + * desired event identified by the tuple: (proto_id, evt_id, src_id) + * + * using the following + * - scmi_register_event_notifier() / scmi_unregister_event_notifier() + * + * where: + * + * @proto_id: The protocol ID as in SCMI Specification + * @evt_id: The message ID of the desired event as in SCMI Specification + * @src_id: A pointer to the desired source ID if different sources are + * possible for the protocol (like domain_id, sensor_id...etc) + * + * @src_id can be provided as NULL if it simply does NOT make sense for + * the protocol at hand, OR if the user is explicitly interested in + * receiving notifications from ANY existent source associated to the + * specified proto_id / evt_id. + * + * Received notifications are finally delivered to the registered users, + * invoking the callback provided with the notifier_block *nb as follows: + * + * int user_cb(nb, evt_id, report) + * + * where: + * + * @nb: The notifier block provided by the user + * @evt_id: The message ID of the delivered event + * @report: A custom struct describing the specific event delivered + */ +int scmi_register_event_notifier(u8 proto_id, u8 evt_id, u32 *src_id, + struct notifier_block *nb); +int scmi_unregister_event_notifier(u8 proto_id, u8 evt_id, u32 *src_id, + struct notifier_block *nb); + +#endif /* _LINUX_SCMI_PROTOCOL_H */ From patchwork Fri Feb 14 15:35:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11382555 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1963013A4 for ; Fri, 14 Feb 2020 15:38:31 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D52F52467C for ; Fri, 14 Feb 2020 15:38:30 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="KsfZkWjk" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D52F52467C Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=inWx8cDycvn7yZFGB88iElDlqA2tljKZ1cbFbfrrPMM=; b=KsfZkWjkv2PNFSTZue4Vi5qRRf FilPqQkw09hpWhsDKjdwI74vVXXYk7IL5kNPMwntGyZkbNUwnNgFPfZp06SwDOfeTJD2jkF+KE/dG qGUBJjZl3uk/97Ed6v53iH0ne1NX2II4eI5niJpopaMfjcXapM4z0F6JN6wTJrMhhiVGn/CHFuAGv eE6W/TYexag0+GcZ3JM4ui3W0/EGzuPJvueZFQ9vFwkmZkIjxBDEUFPeSrSEmyYxibwmn9E4NvjJp UUybc1KxjjBoE+hFk/kP4ZQGqPjCbRe79Xodv36C0W6Px4PsDBKtWsM2TzcGSNY9pSaYoB4YuTo2e mFv3TTEA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d2t-0003Vw-1a; Fri, 14 Feb 2020 15:38:23 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d18-0001gx-T8 for linux-arm-kernel@lists.infradead.org; Fri, 14 Feb 2020 15:36:37 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 3B2AE106F; Fri, 14 Feb 2020 07:36:34 -0800 (PST) Received: from e120937-lin.cambridge.arm.com (e120937-lin.cambridge.arm.com [10.1.197.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 3A1E53F68E; Fri, 14 Feb 2020 07:36:33 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 07/13] firmware: arm_scmi: Add notification dispatch and delivery Date: Fri, 14 Feb 2020 15:35:29 +0000 Message-Id: <20200214153535.32046-8-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200214153535.32046-1-cristian.marussi@arm.com> References: <20200214153535.32046-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200214_073635_056417_68842021 X-CRM114-Status: GOOD ( 27.41 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.3 on bombadil.infradead.org summary: Content analysis details: (-2.3 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [217.140.110.172 listed in list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jonathan.Cameron@Huawei.com, cristian.marussi@arm.com, james.quinlan@broadcom.com, lukasz.luba@arm.com, sudeep.holla@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Add core SCMI Notifications dispatch and delivery support logic which is able, at first, to dispatch well-known received events from the RX ISR to the dedicated deferred worker, and then, from there, to final deliver the events to the registered users' callbacks. Dispatch and delivery is just added here, still not enabled. Signed-off-by: Cristian Marussi --- V1 --> V2 - splitted out of V1 patch 04 - moved from IDR maps to real HashTables to store event_handlers - simplified delivery logic --- drivers/firmware/arm_scmi/notify.c | 242 ++++++++++++++++++++++++++++- drivers/firmware/arm_scmi/notify.h | 22 +++ 2 files changed, 262 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c index 1339b6de0a4c..c2341c5304cf 100644 --- a/drivers/firmware/arm_scmi/notify.c +++ b/drivers/firmware/arm_scmi/notify.c @@ -48,13 +48,44 @@ * particular event coming only from a well defined source (like CPU vs GPU). * When the source is not specified the user callback will be registered for * all existing sources for that event (if any). + * + * Upon reception of a notification message from the platform the SCMI RX ISR + * passes the received message payload and some ancillary information (including + * an arrival timestamp in nanoseconds) to the core via @scmi_notify(), which, + * in turn, after having looked up the event in @scmi_registered_events, pushes + * the event-data itself on a protocol dedicated kfifo queue for further + * deferred processing. + * + * Such dedicated protocols' queues are allocated once for all at initialization + * time, together with a dedicated work_item running the common delivery logic + * of @scmi_events_dispatcher(), so that each protocol has it own dedicated + * work_item and worker which, once kicked by the ISR, takes care to empty its + * own dedicated queue deliverying the queued items into the proper chain. + * + * Note that since the underlying cmwq workers run one distinct work_item per + * protocol and we allow for multiple concurrent workers (max_active != 1), + * notifications processing can proceed concurrently on distinct workers only + * between events belonging to different protocols: delivery of events within + * the same protocol is still strictly sequentially ordered by time of arrival; + * this separation of queues by protocol effectively avoids the possibility that + * one particularly verbose protocol, flooding the queues with events, can cause + * other protocols' events to be lost or their processing starved. + * + * Events' information is then extracted from SCMI Notification messages and + * conveyed, converted into a custom per-event report struct, as the void *data + * param to the user callback provided by the registered notifier_block, so that + * from the user perspective his callback will look invoked like: + * + * int user_cb(struct notifier_block *nb, unsigned long event_id, void *report) + * */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -#include #include +#include +#include #include #include #include @@ -108,6 +139,8 @@ /* A couple of utility macros to limit cruft when calling protocols' helpers */ #define REVT_NOTIFY_ENABLE(revt, ...) \ ((revt)->proto->ops->set_notify_enabled(__VA_ARGS__)) +#define REVT_FILL_REPORT(revt, ...) \ + ((revt)->proto->ops->fill_custom_report(__VA_ARGS__)) /** * events_queue - Describes a queue and its associated worker @@ -117,11 +150,15 @@ * @sz: Size in bytes of the related kfifo * @qbuf: Pre-allocated buffer of @sz bytes to be used by the kfifo * @kfifo: A dedicated Kernel kfifo + * @notify_work: A custom work item bound to this queue + * @wq: A reference to the related workqueue */ struct events_queue { size_t sz; u8 *qbuf; struct kfifo kfifo; + struct work_struct notify_work; + struct workqueue_struct *wq; }; /** @@ -160,6 +197,8 @@ struct scmi_registered_protocol_events_desc { * @scratch_isr: A pre-allocated buffer to be used as a scratch area by ISR * @scratch_isr: A pre-allocated buffer to be used as a scratch area by the * deferred worker + * @report: A pre-allocated buffer used by the deferred worker to fill a + * customized event report * @hash: The hash list_node used for collision handling * @num_sources: The number of possible sources for this event as stated at * events' registration time @@ -173,6 +212,7 @@ struct scmi_registered_event { const struct scmi_event *evt; void *scratch_isr; void *scratch_bh; + void *report; struct hlist_node hash; u32 num_sources; refcount_t *sources; @@ -251,8 +291,191 @@ static DECLARE_HASHTABLE(scmi_registered_events_handlers, 8); */ static DEFINE_MUTEX(scmi_registered_events_handler_mtx); +/* Common Kernel cmwq workqueue used by notifications core */ +static struct workqueue_struct *scmi_notify_wq; + static atomic_t scmi_notifications_initialized = ATOMIC_INIT(0); +static struct scmi_event_handler *scmi_get_event_handler(u32 evt_key); +static void scmi_put_event_handler(struct scmi_event_handler *hndl); + +/** + * scmi_discard_bad_evt_payload() - Utility to discard data from a kfifo + * + * @kq: The kfifo to act on + * @count: Number of bytes to flush + */ +static inline void scmi_discard_bad_evt_payload(struct kfifo *kq, + const unsigned int count) +{ + int i = 0; + + pr_warn("SCMI Notifications: WQ skipping bad EVT Payload - %d bytes\n", + count); + /* Discard stale pending queued payload. */ + for (i = 0; i < count; i++) + kfifo_skip(kq); +} + +/** + * scmi_lookup_and_call_event_chain - Lookup the proper chain and call it + * + * @evt_key: The key to use to lookup the related notification chain + * @report: The customized event-specific report to pass down to the callbacks + * as their *data parameter. + */ +static inline void scmi_lookup_and_call_event_chain(u32 evt_key, void *report) +{ + int ret; + struct scmi_event_handler *hndl; + + /* Here ensure the event handler cannot vanish while using it */ + hndl = scmi_get_event_handler(evt_key); + if (IS_ERR_OR_NULL(hndl)) + return; + + ret = blocking_notifier_call_chain(&hndl->chain, + KEY_XTRACT_EVT_ID(evt_key), + report); + /* Notifiers are NOT supposed to cut the chain */ + WARN_ON_ONCE(ret & NOTIFY_STOP_MASK); + + scmi_put_event_handler(hndl); +} + +/** + * scmi_events_dispatcher - Common worker logic for all work items. + * + * In turn: + * 1. dequeue one pending RX notification (queued in SCMI RX ISR context) + * 2. generate a custom event report from the received event message + * 3. lookup for any registered ALL_SRC_IDs handler + * - > call the related notification chain passing in the report + * 4. lookup for any registered specific SRC_ID handler + * - > call the related notification chain passing in the report + * + * Note that: + * - a dedicated per-protocol kfifo queue is used: in this way an anomalous + * flood of events cannot saturate other protocols' queues. + * + * - each per-protocol queue is associated to a distinct work_item, which + * means, in turn, that: + * + all protocols can process their dedicated queues concurrently + * (since scmi_notify_wq:max_active != 1) + * + anyway at most one worker instance is allowed to run on the same queue + * concurrently: this ensures that we can have only one concurrent + * reader/writer on the associated kfifo, and enables us to use the kfifo + * in a lock-less manner + * + * @work: The work item to use, which is associated to a dedicated events_queue + */ +static void scmi_events_dispatcher(struct work_struct *work) +{ + struct events_queue *equeue; + struct scmi_event_header eh; + + equeue = container_of(work, struct events_queue, notify_work); + /* Read the scmi_event_header at first since it contains payld_sz ... */ + while (kfifo_out(&equeue->kfifo, &eh, sizeof(eh))) { + u32 src_id, key; + unsigned int outs; + struct scmi_registered_event *r_evt; + void *report = NULL; + + key = MAKE_HASH_KEY(eh.proto_id, eh.evt_id, SCMI_ALL_SRC_IDS); + r_evt = KEY_FIND(scmi_registered_events, r_evt, key); + if (!r_evt) { + scmi_discard_bad_evt_payload(&equeue->kfifo, + eh.payld_sz); + continue; + } + + /* ... then read payld_sz bytes holding the evt-msg payload */ + outs = kfifo_out(&equeue->kfifo, r_evt->scratch_bh, + eh.payld_sz); + if (outs != eh.payld_sz) { + pr_warn("SCMI Notifications: WQ SKIP corrupted EVT Payload.\n"); + continue; + } + + + /* Reset and fill custom report, and obtain src_id */ + memset(r_evt->report, 0x00, r_evt->evt->max_report_sz); + report = REVT_FILL_REPORT(r_evt, eh.evt_id, eh.timestamp, + r_evt->scratch_bh, eh.payld_sz, + r_evt->report, &src_id); + if (!report) + continue; + + /* At first search for a generic ALL src_ids handler... */ + scmi_lookup_and_call_event_chain(key, report); + /* ...then search for any specific src_id */ + key = MAKE_HASH_KEY(eh.proto_id, eh.evt_id, src_id); + scmi_lookup_and_call_event_chain(key, report); + } +} + +/** + * scmi_notify - Queues a notification for further deferred processing + * + * This is called in interrupt context to queue a received event for + * deferred processing. + * + * @proto_id: Protocol ID + * @evt_id: Event ID (msgID) + * @buf: Event Message Payload (without the header) + * @len: Event Message Payload size + * @ts: RX Timestamp in nanoseconds (boottime) + * + * Return: 0 on Success + */ +int scmi_notify(u8 proto_id, u8 evt_id, const void *buf, size_t len, u64 ts) +{ + struct scmi_registered_event *r_evt; + struct scmi_event_header *eh; + + + /* Ensure atomic value is updated */ + smp_mb__before_atomic(); + if (unlikely(!atomic_read(&scmi_notifications_initialized))) + return 0; + + r_evt = KEY_FIND(scmi_registered_events, r_evt, + MAKE_HASH_KEY(proto_id, evt_id, SCMI_ALL_SRC_IDS)); + if (unlikely(!r_evt)) + return -EINVAL; + + if (unlikely(len > r_evt->evt->max_payld_sz)) { + pr_err("SCMI Notifications: discard badly sized message\n"); + return -EINVAL; + } + if (unlikely(kfifo_avail(&r_evt->proto->equeue->kfifo) < + sizeof(*eh) + len)) { + pr_warn("SCMI Notifications: queue full dropping proto_id:%d evt_id:%d ts:%lld\n", + proto_id, evt_id, ts); + return -ENOMEM; + } + + /* + * Note that we can use the per protocol kfifo in a lock-less manner + * since we have only one concurrent reader and writer but, in order + * to avoid any trouble on the reader side, here we ensure to perform + * one single kfifo write, so we have to collate in advance the event + * header and payload in a scratch area at first. + */ + eh = r_evt->scratch_isr; + eh->timestamp = ts; + eh->proto_id = proto_id; + eh->evt_id = evt_id; + eh->payld_sz = len; + memcpy(eh->payld, buf, eh->payld_sz); + kfifo_in(&r_evt->proto->equeue->kfifo, eh, sizeof(*eh) + eh->payld_sz); + queue_work(r_evt->proto->equeue->wq, + &r_evt->proto->equeue->notify_work); + + return 0; +} + /** * scmi_allocate_events_queue - Allocate/Initialize an events_queue descriptor * @@ -278,10 +501,11 @@ static struct events_queue *scmi_allocate_events_queue(struct device *dev, if (!equeue->qbuf) return ERR_PTR(-ENOMEM); equeue->sz = sz; - ret = kfifo_init(&equeue->kfifo, equeue->qbuf, equeue->sz); if (ret) return ERR_PTR(ret); + INIT_WORK(&equeue->notify_work, scmi_events_dispatcher); + equeue->wq = scmi_notify_wq; return equeue; } @@ -400,6 +624,11 @@ int scmi_register_protocol_events(struct device *dev, if (!r_evt->scratch_bh) goto err; + r_evt->report = devm_kzalloc(dev, evt->max_report_sz, + GFP_KERNEL); + if (!r_evt->report) + goto err; + r_evt->key = MAKE_HASH_KEY(r_evt->proto->id, r_evt->evt->evt_id, SCMI_ALL_SRC_IDS); @@ -494,6 +723,8 @@ bool scmi_stop_and_flush_protocol_events(u8 proto_id) /* Ensure atomic value is updated */ smp_mb__after_atomic(); + cancel_work_sync(&pdesc->equeue->notify_work); + return true; } @@ -840,6 +1071,11 @@ static struct scmi_notify_ops notify_ops = { */ int scmi_notification_init(struct scmi_handle *handle) { + scmi_notify_wq = alloc_workqueue("scmi_notify", + WQ_UNBOUND | WQ_FREEZABLE, 0); + if (!scmi_notify_wq) + return -ENOMEM; + hash_init(scmi_registered_protocols); hash_init(scmi_registered_events); hash_init(scmi_registered_events_handlers); @@ -861,4 +1097,6 @@ int scmi_notification_init(struct scmi_handle *handle) void scmi_notification_exit(void) { pr_info("SCMI Notifications Core disabled.\n"); + /* Destroy while letting pending work complete */ + destroy_workqueue(scmi_notify_wq); } diff --git a/drivers/firmware/arm_scmi/notify.h b/drivers/firmware/arm_scmi/notify.h index 438181147fc8..bcc599822bf5 100644 --- a/drivers/firmware/arm_scmi/notify.h +++ b/drivers/firmware/arm_scmi/notify.h @@ -9,9 +9,22 @@ #ifndef _SCMI_NOTIFY_H #define _SCMI_NOTIFY_H +#include #include +#include #include +#define MAP_EVT_TO_ENABLE_CMD(id, map) \ +({ \ + int ret = -1; \ + \ + if (likely((id) < ARRAY_SIZE((map)))) \ + ret = (map)[(id)]; \ + else \ + WARN(1, "UN-KNOWN evt_id:%d\n", (id)); \ + ret; \ +}) + /** * scmi_event - Describes an event to be supported * @@ -26,6 +39,7 @@ struct scmi_event { u8 evt_id; size_t max_payld_sz; + size_t max_report_sz; }; @@ -38,9 +52,16 @@ struct scmi_event { * using the proper custom protocol commands. * Return true if at least one the required src_id * has been successfully enabled/disabled + * @fill_custom_report: fills a custom event report from the provided + * event message payld identifying the event + * specific src_id. + * Return NULL on failure otherwise @report now fully + * populated */ struct scmi_protocol_event_ops { bool (*set_notify_enabled)(u8 evt_id, u32 src_id, bool enabled); + void *(*fill_custom_report)(u8 evt_id, u64 timestamp, const void *payld, + size_t payld_sz, void *report, u32 *src_id); }; int scmi_notification_init(struct scmi_handle *handle); @@ -52,5 +73,6 @@ int scmi_register_protocol_events(struct device *dev, int num_sources); int scmi_unregister_protocol_events(struct device *dev, u8 proto_id); bool scmi_stop_and_flush_protocol_events(u8 proto_id); +int scmi_notify(u8 proto_id, u8 evt_id, const void *buf, size_t len, u64 ts); #endif /* _SCMI_NOTIFY_H */ From patchwork Fri Feb 14 15:35:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11382553 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B5F9813A4 for ; Fri, 14 Feb 2020 15:38:13 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 947322467C for ; Fri, 14 Feb 2020 15:38:13 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="cZseGOkM" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 947322467C Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=LRT+2w9L4yL/1UUSCQP+NlnWMP9nHSolm+O2+lZ0mx8=; b=cZseGOkM6y3lcC8Zlt56jVPBb5 +Uzd0qVLmHEcpF9SA/vOPMY8lAVTlsuTLLvTQ4jRos7WZWQRXtoff+Bq+CABhOUD+dibJaABuB/Mw 7Y5RIiEKrhhqIoU4ENiZ/HTXLmZl7GCzSuZgODpJ7nlDXGJrkvJqhM7DB63skwCWtdkwoZdZRVjFm NLvATpkZ9RiiU+MExTIvuIiZj/2RY5iw8xoz2JuwMaPutSbDLeS0GahI0NzvhtSNPlNpT0fEtLfcU qbwoqSNzxqHn+148fWLyQrNzyd6IjnY3gr7aQcfbpu7oME0MQUrnI/WamQrkJkncmaEC3mq97d7W/ oZZnk5Aw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d2d-0003Ht-CV; Fri, 14 Feb 2020 15:38:07 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d1A-0001iN-Ed for linux-arm-kernel@lists.infradead.org; Fri, 14 Feb 2020 15:36:38 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 6ECF7101E; Fri, 14 Feb 2020 07:36:35 -0800 (PST) Received: from e120937-lin.cambridge.arm.com (e120937-lin.cambridge.arm.com [10.1.197.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 6EAB83F68E; Fri, 14 Feb 2020 07:36:34 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 08/13] firmware: arm_scmi: Enable notification core Date: Fri, 14 Feb 2020 15:35:30 +0000 Message-Id: <20200214153535.32046-9-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200214153535.32046-1-cristian.marussi@arm.com> References: <20200214153535.32046-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200214_073636_580946_EC89532C X-CRM114-Status: GOOD ( 11.06 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.3 on bombadil.infradead.org summary: Content analysis details: (-2.3 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [217.140.110.172 listed in list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jonathan.Cameron@Huawei.com, cristian.marussi@arm.com, james.quinlan@broadcom.com, lukasz.luba@arm.com, sudeep.holla@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Initialize and enable SCMI Notifications core support during bus/driver init and probe phases, so that protocols can start registering their supported events during their initialization, and later users can start enrolling their callbacks for the subset of events their interested in. Signed-off-by: Cristian Marussi --- V1 --> V2 - added timestamping - moved notification init/exit and using devres --- drivers/firmware/arm_scmi/bus.c | 11 +++++++++++ drivers/firmware/arm_scmi/driver.c | 10 ++++++++++ 2 files changed, 21 insertions(+) diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c index db55c43a2cbd..0761f306982f 100644 --- a/drivers/firmware/arm_scmi/bus.c +++ b/drivers/firmware/arm_scmi/bus.c @@ -14,6 +14,7 @@ #include #include "common.h" +#include "notify.h" static DEFINE_IDA(scmi_bus_id); static DEFINE_IDR(scmi_protocols); @@ -90,11 +91,21 @@ static int scmi_dev_probe(struct device *dev) return scmi_drv->probe(scmi_dev); } +static inline void scmi_protocol_events_cleanup(struct scmi_device *scmi_dev) +{ + if (scmi_stop_and_flush_protocol_events(scmi_dev->protocol_id)) + scmi_unregister_protocol_events(scmi_dev->handle->dev, + scmi_dev->protocol_id); +} + static int scmi_dev_remove(struct device *dev) { struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver); struct scmi_device *scmi_dev = to_scmi_dev(dev); + /* Release events resources allocated by scmi_protocol_init() */ + scmi_protocol_events_cleanup(scmi_dev); + if (scmi_drv->remove) scmi_drv->remove(scmi_dev); diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 868cc36a07c9..dc93d608c43c 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -26,6 +26,7 @@ #include #include "common.h" +#include "notify.h" #define CREATE_TRACE_POINTS #include @@ -204,11 +205,13 @@ __scmi_xfer_put(struct scmi_xfers_info *minfo, struct scmi_xfer *xfer) static void scmi_handle_notification(struct scmi_chan_info *cinfo, u32 msg_hdr) { + u64 ts; struct scmi_xfer *xfer; struct device *dev = cinfo->dev; struct scmi_info *info = handle_to_scmi_info(cinfo->handle); struct scmi_xfers_info *minfo = &info->rx_minfo; + ts = ktime_get_boottime_ns(); xfer = scmi_xfer_get(cinfo->handle, minfo); if (IS_ERR(xfer)) { dev_err(dev, "failed to get free message slot (%ld)\n", @@ -221,6 +224,8 @@ static void scmi_handle_notification(struct scmi_chan_info *cinfo, u32 msg_hdr) scmi_dump_header_dbg(dev, &xfer->hdr); info->desc->ops->fetch_notification(cinfo, info->desc->max_msg_size, xfer); + scmi_notify(xfer->hdr.protocol_id, xfer->hdr.id, xfer->rx.buf, + xfer->rx.len, ts); trace_scmi_rx_done(xfer->transfer_id, xfer->hdr.id, xfer->hdr.protocol_id, xfer->hdr.seq, @@ -771,6 +776,9 @@ static int scmi_probe(struct platform_device *pdev) if (ret) return ret; + if (scmi_notification_init(handle)) + dev_err(dev, "SCMI Notifications NOT available.\n"); + ret = scmi_base_protocol_init(handle); if (ret) { dev_err(dev, "unable to communicate with SCMI(%d)\n", ret); @@ -813,6 +821,8 @@ static int scmi_remove(struct platform_device *pdev) struct scmi_info *info = platform_get_drvdata(pdev); struct idr *idr = &info->tx_idr; + scmi_notification_exit(); + mutex_lock(&scmi_list_mutex); if (info->users) ret = -EBUSY; From patchwork Fri Feb 14 15:35:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11382557 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9C8161820 for ; Fri, 14 Feb 2020 15:38:36 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 76C5E2467B for ; Fri, 14 Feb 2020 15:38:36 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="MIWyRebR" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 76C5E2467B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=IS+pYtTnkKfxtZ+x/PnIzX/AMA2Ilbh5de4A5nZ89+Q=; b=MIWyRebRamlT0mF6J/IjBS76gz OdT5iUrhHCAU9GZI5PWjwGfVHtjvUy95MWqFlxfWNx2YyOkrkeutwbgSpwLvoUjiGO4YTySZfndka elPqRuNIybc2rWmjWkTtI7hTuweD1p5jxnqt2TqjcdyIU/6fhRcbIhOe6lyo4sMQFtiiDwCsizDan hX9iZwWYIqT3jU4MHZiHAsoGFxG0eZ+899k5uWQjfinlUOUSVEiX9YsdLXbuinJ4EzCyTn4/5geCt n3k3tJ3GHQGndAXoo+gFLpyeODd/Qsk87q5DE8kcYIG5c2xX3bKgKiOgEOeEOzfv69XEuJDRLwZLT 1okmBpIQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d35-0003iA-Sd; Fri, 14 Feb 2020 15:38:35 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d1B-0001n3-99 for linux-arm-kernel@lists.infradead.org; Fri, 14 Feb 2020 15:36:39 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id A271C113E; Fri, 14 Feb 2020 07:36:36 -0800 (PST) Received: from e120937-lin.cambridge.arm.com (e120937-lin.cambridge.arm.com [10.1.197.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id A29B03F68E; Fri, 14 Feb 2020 07:36:35 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 09/13] firmware: arm_scmi: Add Power notifications support Date: Fri, 14 Feb 2020 15:35:31 +0000 Message-Id: <20200214153535.32046-10-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200214153535.32046-1-cristian.marussi@arm.com> References: <20200214153535.32046-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200214_073637_429095_7964DC6F X-CRM114-Status: GOOD ( 13.12 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.3 on bombadil.infradead.org summary: Content analysis details: (-2.3 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [217.140.110.172 listed in list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jonathan.Cameron@Huawei.com, cristian.marussi@arm.com, james.quinlan@broadcom.com, lukasz.luba@arm.com, sudeep.holla@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Make SCMI Power protocol register with the notification core. Signed-off-by: Cristian Marussi --- V1 --> V2 - simplified .set_notify_enabled() implementation moving the ALL_SRCIDs logic out of protocol. ALL_SRCIDs logic is now in charge of the notification core, together with proper reference counting of enables - switched to devres protocol-registration --- drivers/firmware/arm_scmi/power.c | 127 +++++++++++++++++++++++++++++- include/linux/scmi_protocol.h | 15 ++++ 2 files changed, 141 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c index cf7f0312381b..8bd073bcdf1c 100644 --- a/drivers/firmware/arm_scmi/power.c +++ b/drivers/firmware/arm_scmi/power.c @@ -6,6 +6,7 @@ */ #include "common.h" +#include "notify.h" enum scmi_power_protocol_cmd { POWER_DOMAIN_ATTRIBUTES = 0x3, @@ -48,6 +49,12 @@ struct scmi_power_state_notify { __le32 notify_enable; }; +struct scmi_power_state_notify_payld { + __le32 agent_id; + __le32 domain_id; + __le32 power_state; +}; + struct power_dom_info { bool state_set_sync; bool state_set_async; @@ -61,6 +68,14 @@ struct scmi_power_info { u64 stats_addr; u32 stats_size; struct power_dom_info *dom_info; + const struct scmi_handle *handle; +}; + +static struct scmi_power_info *pinfo; + +static enum scmi_power_protocol_cmd evt_2_cmd[] = { + POWER_STATE_NOTIFY, + POWER_STATE_CHANGE_REQUESTED_NOTIFY, }; static int scmi_power_attributes_get(const struct scmi_handle *handle, @@ -186,11 +201,114 @@ static struct scmi_power_ops power_ops = { .state_get = scmi_power_state_get, }; +static int scmi_power_request_notify(const struct scmi_handle *handle, + u32 domain, int message_id, bool enable) +{ + int ret; + struct scmi_xfer *t; + struct scmi_power_state_notify *notify; + + ret = scmi_xfer_get_init(handle, message_id, SCMI_PROTOCOL_POWER, + sizeof(*notify), 0, &t); + if (ret) + return ret; + + notify = t->tx.buf; + notify->domain = cpu_to_le32(domain); + notify->notify_enable = enable ? cpu_to_le32(BIT(0)) : 0; + + ret = scmi_do_xfer(handle, t); + + scmi_xfer_put(handle, t); + return ret; +} + +static bool scmi_power_set_notify_enabled(u8 evt_id, u32 src_id, bool enable) +{ + int ret, cmd_id; + + cmd_id = MAP_EVT_TO_ENABLE_CMD(evt_id, evt_2_cmd); + if (cmd_id < 0) + return false; + + ret = scmi_power_request_notify(pinfo->handle, src_id, cmd_id, enable); + if (ret) + pr_warn("SCMI Notifications - Proto:%X - FAIL_ENABLE - evt[%X] dom[%d] - ret:%d\n", + SCMI_PROTOCOL_POWER, evt_id, src_id, ret); + + return !ret ? true : false; +} + +static void *scmi_power_fill_custom_report(u8 evt_id, u64 timestamp, + const void *payld, size_t payld_sz, + void *report, u32 *src_id) +{ + void *rep = NULL; + + switch (evt_id) { + case POWER_STATE_CHANGED: + { + const struct scmi_power_state_notify_payld *p = payld; + struct scmi_power_state_changed_report *r = report; + + if (sizeof(*p) != payld_sz) + break; + + r->timestamp = timestamp; + r->agent_id = le32_to_cpu(p->agent_id); + r->domain_id = le32_to_cpu(p->domain_id); + r->power_state = le32_to_cpu(p->power_state); + *src_id = r->domain_id; + rep = r; + break; + } + case POWER_STATE_CHANGE_REQUESTED: + { + const struct scmi_power_state_notify_payld *p = payld; + struct scmi_power_state_change_requested_report *r = report; + + if (sizeof(*p) != payld_sz) + break; + + r->timestamp = timestamp; + r->agent_id = le32_to_cpu(p->agent_id); + r->domain_id = le32_to_cpu(p->domain_id); + r->power_state = le32_to_cpu(p->power_state); + *src_id = r->domain_id; + rep = r; + break; + } + default: + break; + } + + return rep; +} + +static const struct scmi_event power_events[] = { + { + .evt_id = POWER_STATE_CHANGED, + .max_payld_sz = 12, + .max_report_sz = + sizeof(struct scmi_power_state_changed_report), + }, + { + .evt_id = POWER_STATE_CHANGE_REQUESTED, + .max_payld_sz = 12, + .max_report_sz = + sizeof(struct scmi_power_state_change_requested_report), + }, +}; + +static const struct scmi_protocol_event_ops power_event_ops = { + .set_notify_enabled = scmi_power_set_notify_enabled, + .fill_custom_report = scmi_power_fill_custom_report, +}; + static int scmi_power_protocol_init(struct scmi_handle *handle) { int domain; u32 version; - struct scmi_power_info *pinfo; scmi_version_get(handle, SCMI_PROTOCOL_POWER, &version); @@ -214,7 +332,14 @@ static int scmi_power_protocol_init(struct scmi_handle *handle) scmi_power_domain_attributes_get(handle, domain, dom); } + scmi_register_protocol_events(handle->dev, + SCMI_PROTOCOL_POWER, PAGE_SIZE, + &power_event_ops, power_events, + ARRAY_SIZE(power_events), + pinfo->num_domains); + pinfo->version = version; + pinfo->handle = handle; handle->power_ops = &power_ops; handle->power_priv = pinfo; diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index f675f2aa7d87..3ec9f1ffa1bf 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -9,6 +9,7 @@ #define _LINUX_SCMI_PROTOCOL_H #include +#include #include #include @@ -381,4 +382,18 @@ int scmi_register_event_notifier(u8 proto_id, u8 evt_id, u32 *src_id, int scmi_unregister_event_notifier(u8 proto_id, u8 evt_id, u32 *src_id, struct notifier_block *nb); +struct scmi_power_state_changed_report { + ktime_t timestamp; + u32 agent_id; + u32 domain_id; + u32 power_state; +}; + +struct scmi_power_state_change_requested_report { + ktime_t timestamp; + u32 agent_id; + u32 domain_id; + u32 power_state; +}; + #endif /* _LINUX_SCMI_PROTOCOL_H */ From patchwork Fri Feb 14 15:35:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11382559 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2D4EA1580 for ; Fri, 14 Feb 2020 15:39:06 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 06D422467D for ; Fri, 14 Feb 2020 15:39:06 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="UkEjJm2f" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 06D422467D Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=Wwf2/wWPnpQIqLiTQYLAJXc5mxcI4I1F35U2y1VeHlE=; b=UkEjJm2fPq9uZSJS9/8nYgeNuu EimQogE/ibDhtthuVk9xXh7rtObBQnbO7oxNTk1dZ+tmfejOB/pI7WmaZTkGUpDrbziQhlp7nxbf9 AemtJyeu3A+T3bccwNZIgzdsSM0QKNlWqeJgTK8RRE8d7WbZExuFN9OZylVrTorBI38Sgyl5/XcBh /5k8Zv01NlkGjsODR7uA4h771NeNoyOJtJeTg2Mq4DzQO+CTylLdsI6oF7MXErewn9b0s75on4Ljj hu7xjTpA74On/maR57rTp0ChAAxJTh1/pp0lr3VT4F3a8NU3EJhhMfLTTk4zIy1HdBctzJrbj05ng eDpaARLg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d3S-00042J-Rk; Fri, 14 Feb 2020 15:38:58 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d1C-0001fo-0C for linux-arm-kernel@lists.infradead.org; Fri, 14 Feb 2020 15:36:39 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id D7D8B11D4; Fri, 14 Feb 2020 07:36:37 -0800 (PST) Received: from e120937-lin.cambridge.arm.com (e120937-lin.cambridge.arm.com [10.1.197.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id D601A3F68E; Fri, 14 Feb 2020 07:36:36 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 10/13] firmware: arm_scmi: Add Perf notifications support Date: Fri, 14 Feb 2020 15:35:32 +0000 Message-Id: <20200214153535.32046-11-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200214153535.32046-1-cristian.marussi@arm.com> References: <20200214153535.32046-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200214_073638_145889_D4A6C352 X-CRM114-Status: GOOD ( 12.99 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.3 on bombadil.infradead.org summary: Content analysis details: (-2.3 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [217.140.110.172 listed in list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jonathan.Cameron@Huawei.com, cristian.marussi@arm.com, james.quinlan@broadcom.com, lukasz.luba@arm.com, sudeep.holla@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Make SCMI Perf protocol register with the notification core. Signed-off-by: Cristian Marussi --- V1 --> V2 - simplified .set_notify_enabled() implementation moving the ALL_SRCIDs logic out of protocol. ALL_SRCIDs logic is now in charge of the notification core, together with proper reference counting of enables - switched to devres protocol-registration --- drivers/firmware/arm_scmi/perf.c | 135 ++++++++++++++++++++++++++++++- include/linux/scmi_protocol.h | 15 ++++ 2 files changed, 149 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c index 88509ec637d0..c427dcfb99e4 100644 --- a/drivers/firmware/arm_scmi/perf.c +++ b/drivers/firmware/arm_scmi/perf.c @@ -14,6 +14,7 @@ #include #include "common.h" +#include "notify.h" enum scmi_performance_protocol_cmd { PERF_DOMAIN_ATTRIBUTES = 0x3, @@ -86,6 +87,19 @@ struct scmi_perf_notify_level_or_limits { __le32 notify_enable; }; +struct scmi_perf_limits_notify_payld { + __le32 agent_id; + __le32 domain_id; + __le32 range_max; + __le32 range_min; +}; + +struct scmi_perf_level_notify_payld { + __le32 agent_id; + __le32 domain_id; + __le32 performance_level; +}; + struct scmi_msg_resp_perf_describe_levels { __le16 num_returned; __le16 num_remaining; @@ -156,6 +170,14 @@ struct scmi_perf_info { u64 stats_addr; u32 stats_size; struct perf_dom_info *dom_info; + const struct scmi_handle *handle; +}; + +static struct scmi_perf_info *pinfo; + +static enum scmi_performance_protocol_cmd evt_2_cmd[] = { + PERF_NOTIFY_LIMITS, + PERF_NOTIFY_LEVEL, }; static int scmi_perf_attributes_get(const struct scmi_handle *handle, @@ -488,6 +510,29 @@ static int scmi_perf_level_get(const struct scmi_handle *handle, u32 domain, return scmi_perf_mb_level_get(handle, domain, level, poll); } +static int scmi_perf_level_limits_notify(const struct scmi_handle *handle, + u32 domain, int message_id, + bool enable) +{ + int ret; + struct scmi_xfer *t; + struct scmi_perf_notify_level_or_limits *notify; + + ret = scmi_xfer_get_init(handle, message_id, SCMI_PROTOCOL_PERF, + sizeof(*notify), 0, &t); + if (ret) + return ret; + + notify = t->tx.buf; + notify->domain = cpu_to_le32(domain); + notify->notify_enable = enable ? cpu_to_le32(BIT(0)) : 0; + + ret = scmi_do_xfer(handle, t); + + scmi_xfer_put(handle, t); + return ret; +} + static bool scmi_perf_fc_size_is_valid(u32 msg, u32 size) { if ((msg == PERF_LEVEL_GET || msg == PERF_LEVEL_SET) && size == 4) @@ -710,11 +755,92 @@ static struct scmi_perf_ops perf_ops = { .est_power_get = scmi_dvfs_est_power_get, }; +static bool scmi_perf_set_notify_enabled(u8 evt_id, u32 src_id, bool enable) +{ + int ret, cmd_id; + + cmd_id = MAP_EVT_TO_ENABLE_CMD(evt_id, evt_2_cmd); + if (cmd_id < 0) + return false; + + ret = scmi_perf_level_limits_notify(pinfo->handle, + src_id, cmd_id, enable); + if (ret) + pr_warn("SCMI Notifications - Proto:%X - FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n", + SCMI_PROTOCOL_PERF, evt_id, src_id, ret); + + return !ret ? true : false; +} + +static void *scmi_perf_fill_custom_report(u8 evt_id, u64 timestamp, + const void *payld, size_t payld_sz, + void *report, u32 *src_id) +{ + void *rep = NULL; + + switch (evt_id) { + case PERFORMANCE_LIMITS_CHANGED: + { + const struct scmi_perf_limits_notify_payld *p = payld; + struct scmi_perf_limits_report *r = report; + + if (sizeof(*p) != payld_sz) + break; + + r->timestamp = timestamp; + r->agent_id = le32_to_cpu(p->agent_id); + r->domain_id = le32_to_cpu(p->domain_id); + r->range_max = le32_to_cpu(p->range_max); + r->range_min = le32_to_cpu(p->range_min); + *src_id = r->domain_id; + rep = r; + break; + } + case PERFORMANCE_LEVEL_CHANGED: + { + const struct scmi_perf_level_notify_payld *p = payld; + struct scmi_perf_level_report *r = report; + + if (sizeof(*p) != payld_sz) + break; + + r->timestamp = timestamp; + r->agent_id = le32_to_cpu(p->agent_id); + r->domain_id = le32_to_cpu(p->domain_id); + r->performance_level = le32_to_cpu(p->performance_level); + *src_id = r->domain_id; + rep = r; + break; + } + default: + break; + } + + return rep; +} + +static const struct scmi_event perf_events[] = { + { + .evt_id = PERFORMANCE_LIMITS_CHANGED, + .max_payld_sz = 16, + .max_report_sz = sizeof(struct scmi_perf_limits_report), + }, + { + .evt_id = PERFORMANCE_LEVEL_CHANGED, + .max_payld_sz = 12, + .max_report_sz = sizeof(struct scmi_perf_level_report), + }, +}; + +static const struct scmi_protocol_event_ops perf_event_ops = { + .set_notify_enabled = scmi_perf_set_notify_enabled, + .fill_custom_report = scmi_perf_fill_custom_report, +}; + static int scmi_perf_protocol_init(struct scmi_handle *handle) { int domain; u32 version; - struct scmi_perf_info *pinfo; scmi_version_get(handle, SCMI_PROTOCOL_PERF, &version); @@ -742,7 +868,14 @@ static int scmi_perf_protocol_init(struct scmi_handle *handle) scmi_perf_domain_init_fc(handle, domain, &dom->fc_info); } + scmi_register_protocol_events(handle->dev, + SCMI_PROTOCOL_PERF, PAGE_SIZE, + &perf_event_ops, perf_events, + ARRAY_SIZE(perf_events), + pinfo->num_domains); + pinfo->version = version; + pinfo->handle = handle; handle->perf_ops = &perf_ops; handle->perf_priv = pinfo; diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 3ec9f1ffa1bf..da4f8bfda168 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -396,4 +396,19 @@ struct scmi_power_state_change_requested_report { u32 power_state; }; +struct scmi_perf_limits_report { + ktime_t timestamp; + u32 agent_id; + u32 domain_id; + u32 range_max; + u32 range_min; +}; + +struct scmi_perf_level_report { + ktime_t timestamp; + u32 agent_id; + u32 domain_id; + u32 performance_level; +}; + #endif /* _LINUX_SCMI_PROTOCOL_H */ From patchwork Fri Feb 14 15:35:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11382561 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6E0E01580 for ; Fri, 14 Feb 2020 15:39:17 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1F9FA2467D for ; Fri, 14 Feb 2020 15:39:17 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="JAdouYzl" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1F9FA2467D Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=K69qWxmrCuXvN+kvwlZKAG2u2F2LYHXfMXjOAxlcjck=; b=JAdouYzlMSGXgCiiLeAIqlTrEw RzXWbnn415gZNazZJaC0fOD3Zy/5FZKa4otcp6oodQVsKf8no8OyPRh74Z+k58Heg8SunsD15aZyi ePd9G2ZCzF2//msTKaWBLjXHBTsE1sc0r5KaSSCwtaDs1qVRM7M4l+OjACgDzx8CWtdqTMNkzJO0U Z8mLnH4Z6N1xZsrwRMX8PzfGBIHGYYxkQTbgPpqPVLgJ3uhQB/jYg4GyJjrTxTGROfs0stCHoRteL VClKvG55FhJ8eSBCDYPxrFdMBxt7i02WyY3yFop2HcvDeTUwInknXYHGAGdg0vWA144rntS8N0s/V QA84T3mg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d3j-0004Je-Kb; Fri, 14 Feb 2020 15:39:15 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d1D-0001iN-HE for linux-arm-kernel@lists.infradead.org; Fri, 14 Feb 2020 15:36:41 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 1692811FB; Fri, 14 Feb 2020 07:36:39 -0800 (PST) Received: from e120937-lin.cambridge.arm.com (e120937-lin.cambridge.arm.com [10.1.197.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 1741B3F68E; Fri, 14 Feb 2020 07:36:37 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 11/13] firmware: arm_scmi: Add Sensor notifications support Date: Fri, 14 Feb 2020 15:35:33 +0000 Message-Id: <20200214153535.32046-12-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200214153535.32046-1-cristian.marussi@arm.com> References: <20200214153535.32046-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200214_073639_703843_A29A4DC3 X-CRM114-Status: GOOD ( 12.41 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.3 on bombadil.infradead.org summary: Content analysis details: (-2.3 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [217.140.110.172 listed in list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jonathan.Cameron@Huawei.com, cristian.marussi@arm.com, james.quinlan@broadcom.com, lukasz.luba@arm.com, sudeep.holla@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Make SCMI Sensor protocol register with the notification core. Signed-off-by: Cristian Marussi --- V1 --> V2 - simplified .set_notify_enabled() implementation moving the ALL_SRCIDs logic out of protocol. ALL_SRCIDs logic is now in charge of the notification core, together with proper reference counting of enables - switched to devres protocol-registration --- drivers/firmware/arm_scmi/sensors.c | 73 ++++++++++++++++++++++++++++- include/linux/scmi_protocol.h | 7 +++ 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c index db1b1ab303da..99c5c67a9b6d 100644 --- a/drivers/firmware/arm_scmi/sensors.c +++ b/drivers/firmware/arm_scmi/sensors.c @@ -6,6 +6,7 @@ */ #include "common.h" +#include "notify.h" enum scmi_sensor_protocol_cmd { SENSOR_DESCRIPTION_GET = 0x3, @@ -71,6 +72,12 @@ struct scmi_msg_sensor_reading_get { #define SENSOR_READ_ASYNC BIT(0) }; +struct scmi_sensor_trip_notify_payld { + __le32 agent_id; + __le32 sensor_id; + __le32 trip_point_desc; +}; + struct sensors_info { u32 version; int num_sensors; @@ -78,8 +85,11 @@ struct sensors_info { u64 reg_addr; u32 reg_size; struct scmi_sensor_info *sensors; + const struct scmi_handle *handle; }; +static struct sensors_info *sinfo; + static int scmi_sensor_attributes_get(const struct scmi_handle *handle, struct sensors_info *si) { @@ -276,10 +286,64 @@ static struct scmi_sensor_ops sensor_ops = { .reading_get = scmi_sensor_reading_get, }; +static bool scmi_sensor_set_notify_enabled(u8 evt_id, u32 src_id, bool enable) +{ + int ret; + + ret = scmi_sensor_trip_point_notify(sinfo->handle, src_id, enable); + if (ret) + pr_warn("SCMI Notifications - Proto:%X - FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n", + SCMI_PROTOCOL_SENSOR, evt_id, src_id, ret); + + return !ret ? true : false; +} + +static void *scmi_sensor_fill_custom_report(u8 evt_id, u64 timestamp, + const void *payld, size_t payld_sz, + void *report, u32 *src_id) +{ + void *rep = NULL; + + switch (evt_id) { + case SENSOR_TRIP_POINT_EVENT: + { + const struct scmi_sensor_trip_notify_payld *p = payld; + struct scmi_sensor_trip_point_report *r = report; + + if (sizeof(*p) != payld_sz) + break; + + r->timestamp = timestamp; + r->agent_id = le32_to_cpu(p->agent_id); + r->sensor_id = le32_to_cpu(p->sensor_id); + r->trip_point_desc = le32_to_cpu(p->trip_point_desc); + *src_id = r->sensor_id; + rep = r; + break; + } + default: + break; + } + + return rep; +} + +static const struct scmi_event sensor_events[] = { + { + .evt_id = SENSOR_TRIP_POINT_EVENT, + .max_payld_sz = 12, + .max_report_sz = sizeof(struct scmi_sensor_trip_point_report), + }, +}; + +static const struct scmi_protocol_event_ops sensor_event_ops = { + .set_notify_enabled = scmi_sensor_set_notify_enabled, + .fill_custom_report = scmi_sensor_fill_custom_report, +}; + static int scmi_sensors_protocol_init(struct scmi_handle *handle) { u32 version; - struct sensors_info *sinfo; scmi_version_get(handle, SCMI_PROTOCOL_SENSOR, &version); @@ -299,7 +363,14 @@ static int scmi_sensors_protocol_init(struct scmi_handle *handle) scmi_sensor_description_get(handle, sinfo); + scmi_register_protocol_events(handle->dev, + SCMI_PROTOCOL_SENSOR, PAGE_SIZE, + &sensor_event_ops, sensor_events, + ARRAY_SIZE(sensor_events), + sinfo->num_sensors); + sinfo->version = version; + sinfo->handle = handle; handle->sensor_ops = &sensor_ops; handle->sensor_priv = sinfo; diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index da4f8bfda168..77cf107a7391 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -411,4 +411,11 @@ struct scmi_perf_level_report { u32 performance_level; }; +struct scmi_sensor_trip_point_report { + ktime_t timestamp; + u32 agent_id; + u32 sensor_id; + u32 trip_point_desc; +}; + #endif /* _LINUX_SCMI_PROTOCOL_H */ From patchwork Fri Feb 14 15:35:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11382563 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 44A4813A4 for ; Fri, 14 Feb 2020 15:39:44 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 20B3824680 for ; Fri, 14 Feb 2020 15:39:44 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="nh4tv9J0" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 20B3824680 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=a8nxzrZ9fqALuFaqCSGFPRI10zKRBuPlhFTfr7b2MUA=; b=nh4tv9J0Hh/7lZtONSRtDG/YkD wjSidohwI/3QAtYhQk+f8MQSn5dUteQ0DJo/f+UapDnLtw/3mXRRbcmho1FfHyKYHdF0BcU6cgfL7 BRnqTYUDSG844g9APWZEU/c8LVkLM2I4aaIKmu1XgZXCpPaBuSXFxesIoDSsULrQN3RdG27tyq3jB wQZaTFXmxqS036n4lHzfquZphlwGKLLbHiUG6XIwPVuOf6KkM30gcGLXFvbXvvFKuTy5aeWGBIH3h phMtBsQKrRSDzTHKdwYK9IpNspuiV8QBYR8c+1GekbE+vIw+vdFqtxRCr0Un+1ySed3qELKOotvSu OkecgHyA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d45-0004cJ-8U; Fri, 14 Feb 2020 15:39:37 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d1E-0001n3-E5 for linux-arm-kernel@lists.infradead.org; Fri, 14 Feb 2020 15:36:42 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 4A7F2106F; Fri, 14 Feb 2020 07:36:40 -0800 (PST) Received: from e120937-lin.cambridge.arm.com (e120937-lin.cambridge.arm.com [10.1.197.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 4A5383F6CF; Fri, 14 Feb 2020 07:36:39 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 12/13] firmware: arm_scmi: Add Reset notifications support Date: Fri, 14 Feb 2020 15:35:34 +0000 Message-Id: <20200214153535.32046-13-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200214153535.32046-1-cristian.marussi@arm.com> References: <20200214153535.32046-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200214_073640_618022_9D31BEB0 X-CRM114-Status: GOOD ( 12.88 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.3 on bombadil.infradead.org summary: Content analysis details: (-2.3 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [217.140.110.172 listed in list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jonathan.Cameron@Huawei.com, cristian.marussi@arm.com, james.quinlan@broadcom.com, lukasz.luba@arm.com, sudeep.holla@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Make SCMI Reset protocol register with the notification core. Signed-off-by: Cristian Marussi --- V1 --> V2 - simplified .set_notify_enabled() implementation moving the ALL_SRCIDs logic out of protocol. ALL_SRCIDs logic is now in charge of the notification core, together with proper reference counting of enables - switched to devres protocol-registration --- drivers/firmware/arm_scmi/reset.c | 100 +++++++++++++++++++++++++++++- include/linux/scmi_protocol.h | 6 ++ 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c index de73054554f3..4316d772a0cf 100644 --- a/drivers/firmware/arm_scmi/reset.c +++ b/drivers/firmware/arm_scmi/reset.c @@ -6,6 +6,7 @@ */ #include "common.h" +#include "notify.h" enum scmi_reset_protocol_cmd { RESET_DOMAIN_ATTRIBUTES = 0x3, @@ -40,6 +41,17 @@ struct scmi_msg_reset_domain_reset { #define ARCH_COLD_RESET (ARCH_RESET_TYPE | COLD_RESET_STATE) }; +struct scmi_msg_reset_notify { + __le32 id; + __le32 event_control; +#define RESET_TP_NOTIFY_ALL BIT(0) +}; + +struct scmi_reset_issued_notify_payld { + __le32 domain_id; + __le32 reset_state; +}; + struct reset_dom_info { bool async_reset; bool reset_notify; @@ -51,8 +63,11 @@ struct scmi_reset_info { u32 version; int num_domains; struct reset_dom_info *dom_info; + const struct scmi_handle *handle; }; +static struct scmi_reset_info *pinfo; + static int scmi_reset_attributes_get(const struct scmi_handle *handle, struct scmi_reset_info *pi) { @@ -190,11 +205,87 @@ static struct scmi_reset_ops reset_ops = { .deassert = scmi_reset_domain_deassert, }; +static int scmi_reset_notify(const struct scmi_handle *handle, u32 domain_id, + bool enable) +{ + int ret; + u32 evt_cntl = enable ? RESET_TP_NOTIFY_ALL : 0; + struct scmi_xfer *t; + struct scmi_msg_reset_notify *cfg; + + ret = scmi_xfer_get_init(handle, RESET_NOTIFY, + SCMI_PROTOCOL_RESET, sizeof(*cfg), 0, &t); + if (ret) + return ret; + + cfg = t->tx.buf; + cfg->id = cpu_to_le32(domain_id); + cfg->event_control = cpu_to_le32(evt_cntl); + + ret = scmi_do_xfer(handle, t); + + scmi_xfer_put(handle, t); + return ret; +} + +static bool scmi_reset_set_notify_enabled(u8 evt_id, u32 src_id, bool enable) +{ + int ret; + + ret = scmi_reset_notify(pinfo->handle, src_id, enable); + if (ret) + pr_warn("SCMI Notifications - Proto:%X - FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n", + SCMI_PROTOCOL_RESET, evt_id, src_id, ret); + + return !ret ? true : false; +} + +static void *scmi_reset_fill_custom_report(u8 evt_id, u64 timestamp, + const void *payld, size_t payld_sz, + void *report, u32 *src_id) +{ + void *rep = NULL; + + switch (evt_id) { + case RESET_ISSUED: + { + const struct scmi_reset_issued_notify_payld *p = payld; + struct scmi_reset_issued_report *r = report; + + if (sizeof(*p) != payld_sz) + break; + + r->timestamp = timestamp; + r->domain_id = le32_to_cpu(p->domain_id); + r->reset_state = le32_to_cpu(p->reset_state); + *src_id = r->domain_id; + rep = r; + break; + } + default: + break; + } + + return rep; +} + +static const struct scmi_event reset_events[] = { + { + .evt_id = RESET_NOTIFY, + .max_payld_sz = 8, + .max_report_sz = sizeof(struct scmi_reset_issued_report), + }, +}; + +static const struct scmi_protocol_event_ops reset_event_ops = { + .set_notify_enabled = scmi_reset_set_notify_enabled, + .fill_custom_report = scmi_reset_fill_custom_report, +}; + static int scmi_reset_protocol_init(struct scmi_handle *handle) { int domain; u32 version; - struct scmi_reset_info *pinfo; scmi_version_get(handle, SCMI_PROTOCOL_RESET, &version); @@ -218,7 +309,14 @@ static int scmi_reset_protocol_init(struct scmi_handle *handle) scmi_reset_domain_attributes_get(handle, domain, dom); } + scmi_register_protocol_events(handle->dev, + SCMI_PROTOCOL_RESET, PAGE_SIZE, + &reset_event_ops, reset_events, + ARRAY_SIZE(reset_events), + pinfo->num_domains); + pinfo->version = version; + pinfo->handle = handle; handle->reset_ops = &reset_ops; handle->reset_priv = pinfo; diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 77cf107a7391..e6d4fc01d560 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -418,4 +418,10 @@ struct scmi_sensor_trip_point_report { u32 trip_point_desc; }; +struct scmi_reset_issued_report { + ktime_t timestamp; + u32 domain_id; + u32 reset_state; +}; + #endif /* _LINUX_SCMI_PROTOCOL_H */ From patchwork Fri Feb 14 15:35:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11382565 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D44DA13A4 for ; Fri, 14 Feb 2020 15:40:03 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5C49F2467E for ; Fri, 14 Feb 2020 15:40:03 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="BJuWvTtc" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5C49F2467E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=XBIE0MZeIV3hd5ghXApAGFTJ6haBNapL8Xv02Thrdp0=; b=BJuWvTtcmmYqPIVrOsvcTl1GYL s2zCYGgguryNoACNKl53K+XZWzO4vJo1quOA9DsmG+e9+lKXzAKssjSsXyGlxbL4O3AEtu+LOgZ7M 1kSTnfPtNdoqlRj0Ho9RYjNOpeoq8DmZ0d3C8HvxTEqn8l+5WMw1bs4ynHzckM7VrIGwHJGk3xY3T gwsU93GJLcDMTXuOjrozIaBmUylG+mRwoQ1XPLcUO24rICWI6IfpL8CGuMV3hg9lPi8An9zRNSkg2 T5vsDikmTdMRRT2O08YL0SvUR7G6U0xYup5AcPb4hX2abhQlbWD2MOQxs0jHrP+VEy8Yakwh3tCAy y4Bc/mgQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d4O-0004r5-FI; Fri, 14 Feb 2020 15:39:56 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j2d1F-0001iN-Kd for linux-arm-kernel@lists.infradead.org; Fri, 14 Feb 2020 15:36:43 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 7F1B9101E; Fri, 14 Feb 2020 07:36:41 -0800 (PST) Received: from e120937-lin.cambridge.arm.com (e120937-lin.cambridge.arm.com [10.1.197.50]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 7E1923F68E; Fri, 14 Feb 2020 07:36:40 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 13/13] firmware: arm_scmi: Add Base notifications support Date: Fri, 14 Feb 2020 15:35:35 +0000 Message-Id: <20200214153535.32046-14-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200214153535.32046-1-cristian.marussi@arm.com> References: <20200214153535.32046-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200214_073641_777772_932E2EF7 X-CRM114-Status: GOOD ( 14.47 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.3 on bombadil.infradead.org summary: Content analysis details: (-2.3 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [217.140.110.172 listed in list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jonathan.Cameron@Huawei.com, cristian.marussi@arm.com, james.quinlan@broadcom.com, lukasz.luba@arm.com, sudeep.holla@arm.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Make SCMI Base protocol register with the notification core. Signed-off-by: Cristian Marussi --- V1 --> V2 - simplified .set_notify_enabled() implementation moving the ALL_SRCIDs logic out of protocol. ALL_SRCIDs logic is now in charge of the notification core, together with proper reference counting of enables - switched to devres protocol-registration --- drivers/firmware/arm_scmi/base.c | 114 +++++++++++++++++++++++++++++++ include/linux/scmi_protocol.h | 8 +++ 2 files changed, 122 insertions(+) diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c index ce7d9203e41b..df9fae9a0cff 100644 --- a/drivers/firmware/arm_scmi/base.c +++ b/drivers/firmware/arm_scmi/base.c @@ -6,6 +6,9 @@ */ #include "common.h" +#include "notify.h" + +#define SCMI_BASE_NUM_SOURCES 1 enum scmi_base_protocol_cmd { BASE_DISCOVER_VENDOR = 0x3, @@ -29,6 +32,21 @@ struct scmi_msg_resp_base_attributes { __le16 reserved; }; +struct scmi_msg_base_error_notify { + __le32 event_control; +#define BASE_TP_NOTIFY_ALL BIT(0) +}; + +struct scmi_base_error_notify_payld { + __le32 agent_id; + __le32 error_status; +#define IS_FATAL_ERROR(x) ((x) & BIT(31)) +#define ERROR_CMD_COUNT(x) FIELD_GET(GENMASK(9, 0), (x)) + __le64 msg_reports[8192]; +}; + +static const struct scmi_handle *protocol_handle; + /** * scmi_base_attributes_get() - gets the implementation details * that are associated with the base protocol. @@ -222,6 +240,95 @@ static int scmi_base_discover_agent_get(const struct scmi_handle *handle, return ret; } +static int scmi_base_error_notify(const struct scmi_handle *handle, bool enable) +{ + int ret; + u32 evt_cntl = enable ? BASE_TP_NOTIFY_ALL : 0; + struct scmi_xfer *t; + struct scmi_msg_base_error_notify *cfg; + + ret = scmi_xfer_get_init(handle, BASE_NOTIFY_ERRORS, + SCMI_PROTOCOL_BASE, sizeof(*cfg), 0, &t); + if (ret) + return ret; + + cfg = t->tx.buf; + cfg->event_control = cpu_to_le32(evt_cntl); + + ret = scmi_do_xfer(handle, t); + + scmi_xfer_put(handle, t); + return ret; +} + +static bool scmi_base_set_notify_enabled(u8 evt_id, u32 src_id, bool enable) +{ + int ret; + + if (!protocol_handle) + return false; + + ret = scmi_base_error_notify(protocol_handle, enable); + if (ret) + pr_warn("SCMI Notifications - Proto:%X - FAIL_ENABLED - evt[%X] ret:%d\n", + SCMI_PROTOCOL_BASE, evt_id, ret); + + return !ret ? true : false; +} + +static void *scmi_base_fill_custom_report(u8 evt_id, u64 timestamp, + const void *payld, size_t payld_sz, + void *report, u32 *src_id) +{ + void *rep = NULL; + + switch (evt_id) { + case BASE_ERROR_EVENT: + { + int i; + const struct scmi_base_error_notify_payld *p = payld; + struct scmi_base_error_report *r = report; + + /* + * BaseError notification payload is variable in size but + * up to a maximum length determined by the struct ponted by p. + * Instead payld_sz is the effective length of this notification + * payload so cannot be greater of the maximum allowed size as + * pointed by p. + */ + if (sizeof(*p) < payld_sz) + break; + + r->timestamp = timestamp; + r->agent_id = le32_to_cpu(p->agent_id); + r->fatal = IS_FATAL_ERROR(le32_to_cpu(p->error_status)); + r->cmd_count = ERROR_CMD_COUNT(le32_to_cpu(p->error_status)); + for (i = 0; i < r->cmd_count; i++) + r->reports[i] = le64_to_cpu(p->msg_reports[i]); + *src_id = 0; + rep = r; + break; + } + default: + break; + } + + return rep; +} + +static const struct scmi_event base_events[] = { + { + .evt_id = BASE_ERROR_EVENT, + .max_payld_sz = 8192, + .max_report_sz = sizeof(struct scmi_base_error_report), + }, +}; + +static const struct scmi_protocol_event_ops base_event_ops = { + .set_notify_enabled = scmi_base_set_notify_enabled, + .fill_custom_report = scmi_base_fill_custom_report, +}; + int scmi_base_protocol_init(struct scmi_handle *h) { int id, ret; @@ -256,10 +363,17 @@ int scmi_base_protocol_init(struct scmi_handle *h) dev_dbg(dev, "Found %d protocol(s) %d agent(s)\n", rev->num_protocols, rev->num_agents); + scmi_register_protocol_events(handle->dev, + SCMI_PROTOCOL_BASE, (4 * PAGE_SIZE), + &base_event_ops, base_events, + ARRAY_SIZE(base_events), + SCMI_BASE_NUM_SOURCES); + for (id = 0; id < rev->num_agents; id++) { scmi_base_discover_agent_get(handle, id, name); dev_dbg(dev, "Agent %d: %s\n", id, name); } + protocol_handle = handle; return 0; } diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index e6d4fc01d560..16b184a36c22 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -424,4 +424,12 @@ struct scmi_reset_issued_report { u32 reset_state; }; +struct scmi_base_error_report { + ktime_t timestamp; + u32 agent_id; + bool fatal; + u16 cmd_count; + u64 reports[8192]; +}; + #endif /* _LINUX_SCMI_PROTOCOL_H */