From patchwork Wed Oct 14 15:05: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: 11837833 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 A6D9814B5 for ; Wed, 14 Oct 2020 15:07:22 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (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 49EB521582 for ; Wed, 14 Oct 2020 15:07:22 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="wHJFWCEW" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 49EB521582 Authentication-Results: mail.kernel.org; dmarc=fail (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=merlin.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=9RrM23LCqteNxDXi38NFEHIVrQbGqTRteC5VTWxyfcA=; b=wHJFWCEWk9Y+fkTbltrnROa7K7 olh72xIpG/W4Y/rQnNJjbO1JQwdfKwbcv/wJmwyo9YT6GlnQtvqT7sL8YSCMf9rhvBnyNp9we15Bp /XXdjQkRMiBJ2uc2VCQfC2yXCOKN19ae+XGq4ANuybNlg2qiSyKcLYCBJyaxq6bs9q8VPcif/3dYi V51u22C9uUYCjfaRwaR1klOwfOG7bRMa7g3g5OdZrm+9ia1QpcwjxFbIbvliJPm6RBmgV4yESaANA dY0oV+jIhepkpajoz3Hun5MToRJhFzDS0ROS+o9vd6qOZcEmG1+y3FhkW6MFlYyXOjw4NAgKV9gBz uwbCe3Ig==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kSiMq-0001Kj-Nw; Wed, 14 Oct 2020 15:07:04 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kSiMi-0001Hj-CM for linux-arm-kernel@lists.infradead.org; Wed, 14 Oct 2020 15:06:57 +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 4D2AE1424; Wed, 14 Oct 2020 08:06:55 -0700 (PDT) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 931213F71F; Wed, 14 Oct 2020 08:06:53 -0700 (PDT) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH 01/11] firmware: arm_scmi: review protocol registration interface Date: Wed, 14 Oct 2020 16:05:35 +0100 Message-Id: <20201014150545.44807-2-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201014150545.44807-1-cristian.marussi@arm.com> References: <20201014150545.44807-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201014_110656_518763_09A97336 X-CRM114-Status: GOOD ( 25.90 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.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: f.fainelli@gmail.com, vincent.guittot@linaro.org, sudeep.holla@arm.com, thara.gopinath@linaro.org, cristian.marussi@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, souvik.chakravarty@arm.com, etienne.carriere@linaro.org, lukasz.luba@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 Extend common protocol registration routines and provide some new generic protocols' init/deinit helpers that tracks protocols' users and automatically perform the proper initialization/de-initialization on demand. Convert all protocols to use new registration schema while modifying only Base protocol to use also the new initialization helpers. All other standard protocols' initialization is still umodified and bound to SCMI devices probing. Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/base.c | 10 +- drivers/firmware/arm_scmi/bus.c | 61 +++++++--- drivers/firmware/arm_scmi/clock.c | 10 +- drivers/firmware/arm_scmi/common.h | 31 ++++- drivers/firmware/arm_scmi/driver.c | 168 +++++++++++++++++++++++++++- drivers/firmware/arm_scmi/notify.c | 3 +- drivers/firmware/arm_scmi/perf.c | 10 +- drivers/firmware/arm_scmi/power.c | 10 +- drivers/firmware/arm_scmi/reset.c | 10 +- drivers/firmware/arm_scmi/sensors.c | 10 +- drivers/firmware/arm_scmi/system.c | 8 +- include/linux/scmi_protocol.h | 6 +- 12 files changed, 298 insertions(+), 39 deletions(-) diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c index 017e5d8bd869..f19e08ed4369 100644 --- a/drivers/firmware/arm_scmi/base.c +++ b/drivers/firmware/arm_scmi/base.c @@ -318,7 +318,7 @@ static const struct scmi_event_ops base_event_ops = { .fill_custom_report = scmi_base_fill_custom_report, }; -int scmi_base_protocol_init(struct scmi_handle *h) +static int scmi_base_protocol_init(struct scmi_handle *h) { int id, ret; u8 *prot_imp; @@ -365,3 +365,11 @@ int scmi_base_protocol_init(struct scmi_handle *h) return 0; } + +static struct scmi_protocol scmi_base = { + .id = SCMI_PROTOCOL_BASE, + .init = &scmi_base_protocol_init, + .ops = NULL, +}; + +DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(base, scmi_base) diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c index 1377ec76a45d..afa2e4818a2b 100644 --- a/drivers/firmware/arm_scmi/bus.c +++ b/drivers/firmware/arm_scmi/bus.c @@ -16,7 +16,7 @@ #include "common.h" static DEFINE_IDA(scmi_bus_id); -static DEFINE_IDR(scmi_protocols); +static DEFINE_IDR(scmi_available_protocols); static DEFINE_SPINLOCK(protocol_lock); static const struct scmi_device_id * @@ -51,13 +51,29 @@ static int scmi_dev_match(struct device *dev, struct device_driver *drv) return 0; } +const struct scmi_protocol *scmi_get_protocol(int protocol_id) +{ + const struct scmi_protocol *proto; + + proto = idr_find(&scmi_available_protocols, protocol_id); + if (!proto) { + pr_warn("SCMI Protocol 0x%x not found!\n", protocol_id); + return NULL; + } + + pr_debug("GOT SCMI Protocol 0x%x\n", protocol_id); + + return proto; +} + static int scmi_protocol_init(int protocol_id, struct scmi_handle *handle) { - scmi_prot_init_fn_t fn = idr_find(&scmi_protocols, protocol_id); + const struct scmi_protocol *proto; - if (unlikely(!fn)) + proto = idr_find(&scmi_available_protocols, protocol_id); + if (!proto) return -EINVAL; - return fn(handle); + return proto->init(handle); } static int scmi_protocol_dummy_init(struct scmi_handle *handle) @@ -84,7 +100,7 @@ static int scmi_dev_probe(struct device *dev) return ret; /* Skip protocol initialisation for additional devices */ - idr_replace(&scmi_protocols, &scmi_protocol_dummy_init, + idr_replace(&scmi_available_protocols, &scmi_protocol_dummy_init, scmi_dev->protocol_id); return scmi_drv->probe(scmi_dev); @@ -194,26 +210,45 @@ void scmi_set_handle(struct scmi_device *scmi_dev) scmi_dev->handle = scmi_handle_get(&scmi_dev->dev); } -int scmi_protocol_register(int protocol_id, scmi_prot_init_fn_t fn) +int scmi_protocol_register(struct scmi_protocol *proto) { int ret; + if (!proto) { + pr_err("invalid protocol\n"); + return -EINVAL; + } + + if (!proto->init) { + pr_err("missing .init() for protocol 0x%x\n", proto->id); + return -EINVAL; + } + spin_lock(&protocol_lock); - ret = idr_alloc(&scmi_protocols, fn, protocol_id, protocol_id + 1, - GFP_ATOMIC); + ret = idr_alloc(&scmi_available_protocols, proto, + proto->id, proto->id + 1, GFP_ATOMIC); spin_unlock(&protocol_lock); - if (ret != protocol_id) - pr_err("unable to allocate SCMI idr slot, err %d\n", ret); + if (ret != proto->id) { + pr_err("unable to allocate SCMI idr slot for 0x%x - err %d\n", + proto->id, ret); + return ret; + } + + pr_debug("Registered SCMI Protocol 0x%x\n", proto->id); - return ret; + return 0; } EXPORT_SYMBOL_GPL(scmi_protocol_register); -void scmi_protocol_unregister(int protocol_id) +void scmi_protocol_unregister(const struct scmi_protocol *proto) { spin_lock(&protocol_lock); - idr_remove(&scmi_protocols, protocol_id); + idr_remove(&scmi_available_protocols, proto->id); spin_unlock(&protocol_lock); + + pr_debug("Unregistered SCMI Protocol 0x%x\n", proto->id); + + return; } EXPORT_SYMBOL_GPL(scmi_protocol_unregister); diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c index 4645677d86f1..94bcad9a7d19 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -2,7 +2,7 @@ /* * System Control and Management Interface (SCMI) Clock Protocol * - * Copyright (C) 2018 ARM Ltd. + * Copyright (C) 2018-2020 ARM Ltd. */ #include @@ -366,4 +366,10 @@ static int scmi_clock_protocol_init(struct scmi_handle *handle) return 0; } -DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_CLOCK, clock) +static struct scmi_protocol scmi_clock = { + .id = SCMI_PROTOCOL_CLOCK, + .init = &scmi_clock_protocol_init, + .ops = &clk_ops, +}; + +DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(clock, scmi_clock) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 65063fa948d4..b08a8ddbc22a 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -19,6 +19,8 @@ #include +#define SCMI_MAX_PROTO 256 + #define PROTOCOL_REV_MINOR_MASK GENMASK(15, 0) #define PROTOCOL_REV_MAJOR_MASK GENMASK(31, 16) #define PROTOCOL_REV_MAJOR(x) (u16)(FIELD_GET(PROTOCOL_REV_MAJOR_MASK, (x))) @@ -156,7 +158,22 @@ int scmi_version_get(const struct scmi_handle *h, u8 protocol, u32 *version); void scmi_setup_protocol_implemented(const struct scmi_handle *handle, u8 *prot_imp); -int scmi_base_protocol_init(struct scmi_handle *h); +typedef int (*scmi_prot_init_fn_t)(struct scmi_handle *); + +/** + * struct scmi_protocol - Protocol descriptor + * @id: Protocol ID. + * @init: Mandatory protocol initialization function. + * @deinit: Optional protocol de-initialization function. + * @ops: Optional reference to the operations provided by the protocol and + * exposed in scmi_protocol.h. + */ +struct scmi_protocol { + const u8 id; + const scmi_prot_init_fn_t init; + const scmi_prot_init_fn_t deinit; + const void *ops; +}; int __init scmi_bus_init(void); void __exit scmi_bus_exit(void); @@ -164,6 +181,7 @@ void __exit scmi_bus_exit(void); #define DECLARE_SCMI_REGISTER_UNREGISTER(func) \ int __init scmi_##func##_register(void); \ void __exit scmi_##func##_unregister(void) +DECLARE_SCMI_REGISTER_UNREGISTER(base); DECLARE_SCMI_REGISTER_UNREGISTER(clock); DECLARE_SCMI_REGISTER_UNREGISTER(perf); DECLARE_SCMI_REGISTER_UNREGISTER(power); @@ -171,17 +189,22 @@ DECLARE_SCMI_REGISTER_UNREGISTER(reset); DECLARE_SCMI_REGISTER_UNREGISTER(sensors); DECLARE_SCMI_REGISTER_UNREGISTER(system); -#define DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(id, name) \ +#define DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(name, proto) \ int __init scmi_##name##_register(void) \ { \ - return scmi_protocol_register((id), &scmi_##name##_protocol_init); \ + return scmi_protocol_register(&(proto)); \ } \ \ void __exit scmi_##name##_unregister(void) \ { \ - scmi_protocol_unregister((id)); \ + scmi_protocol_unregister(&(proto)); \ } +const struct scmi_protocol *scmi_get_protocol(int protocol_id); + +int scmi_acquire_protocol(struct scmi_handle *handle, u8 protocol_id); +void scmi_release_protocol(struct scmi_handle *handle, u8 protocol_id); + /* SCMI Transport */ /** * struct scmi_chan_info - Structure representing a SCMI channel information diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 3dfd8b6a0ebf..7de994e49884 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "common.h" @@ -68,6 +69,21 @@ struct scmi_xfers_info { spinlock_t xfer_lock; }; +/** + * struct scmi_protocol_instance - Describe an initialized protocol instance. + * @proto: A reference to the protocol descriptor. + * @gid: A reference for per-protocol devres management. + * @users: A refcount to track effective users of this protocol. + * + * Each protocol is initialized independently once for each SCMI platform in + * which is defined by DT and implemented by the SCMI server fw. + */ +struct scmi_protocol_instance { + const struct scmi_protocol *proto; + void *gid; + refcount_t users; +}; + /** * struct scmi_info - Structure representing a SCMI instance * @@ -80,6 +96,10 @@ struct scmi_xfers_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: An array of protocols' instance descriptors initialized for + * this SCMI instance: populated on protocol's first attempted + * usage. + * @protocols_mtx: A mutex to protect protocols instances initialization. * @protocols_imp: List of protocols implemented, currently maximum of * MAX_PROTOCOLS_IMP elements allocated by the base protocol * @node: List head @@ -94,6 +114,9 @@ struct scmi_info { struct scmi_xfers_info rx_minfo; struct idr tx_idr; struct idr rx_idr; + struct scmi_protocol_instance *protocols[SCMI_MAX_PROTO]; + /* Ensure mutual exclusive access to protocols instance array */ + struct mutex protocols_mtx; u8 *protocols_imp; struct list_head node; int users; @@ -519,6 +542,132 @@ int scmi_version_get(const struct scmi_handle *handle, u8 protocol, return ret; } +/** + * scmi_get_protocol_instance - Protocol initialization helper. + * @handle: A reference to the SCMI platform instance. + * @protocol_id: The protocol being requested. + * + * In case the required protocol has never been requested before for this + * instance, allocate and initialize all the needed structures while handling + * resource allocation with a dedicated per-protocol devres subgroup. + * + * Return: A reference to an initialized protocol instance or error on failure. + */ +static struct scmi_protocol_instance * __must_check +scmi_get_protocol_instance(struct scmi_handle *handle, u8 protocol_id) +{ + int ret = -ENOMEM; + void *gid; + struct scmi_protocol_instance *pi; + struct scmi_info *info = handle_to_scmi_info(handle); + + mutex_lock(&info->protocols_mtx); + /* Ensure protocols has been updated */ + smp_rmb(); + pi = info->protocols[protocol_id]; + + if (!pi) { + const struct scmi_protocol *proto; + + /* Fail if protocol not registered on bus */ + proto = scmi_get_protocol(protocol_id); + if (!proto) { + ret = -EINVAL; + goto out; + } + + /* Protocol specific devres group */ + gid = devres_open_group(handle->dev, NULL, GFP_KERNEL); + if (!gid) + goto out; + + pi = devm_kzalloc(handle->dev, sizeof(*pi), GFP_KERNEL); + if (!pi) + goto clean; + + pi->gid = gid; + pi->proto = proto; + refcount_set(&pi->users, 1); + /* proto->init is assured NON NULL by scmi_protocol_register */ + ret = pi->proto->init(handle); + if (ret) + goto clean; + + info->protocols[protocol_id] = pi; + /* Ensure initialized protocol is visible */ + smp_wmb(); + + devres_close_group(handle->dev, pi->gid); + dev_dbg(handle->dev, "Initialized protocol: 0x%X\n", + protocol_id); + } else { + refcount_inc(&pi->users); + } + mutex_unlock(&info->protocols_mtx); + + return pi; + +clean: + devres_release_group(handle->dev, gid); +out: + mutex_unlock(&info->protocols_mtx); + return ERR_PTR(ret); +} + +/** + * scmi_acquire_protocol - Protocol acquire + * @handle: A reference to the SCMI platform instance. + * @protocol_id: The protocol being requested. + * + * Register a new user for the requested protocol on the specified SCMI + * platform instance, possibly triggering its initialization on first user. + * + * Return: 0 if protocol was acquired successfully. + */ +int scmi_acquire_protocol(struct scmi_handle *handle, u8 protocol_id) +{ + return IS_ERR(scmi_get_protocol_instance(handle, protocol_id)); +} + +/** + * scmi_release_protocol - Protocol de-initialization helper. + * @handle: A reference to the SCMI platform instance. + * @protocol_id: The protocol being requested. + * + * Remove one user for the specified protocol and triggers de-initialization + * and resources de-allocation once the last user has gone. + */ +void scmi_release_protocol(struct scmi_handle *handle, u8 protocol_id) +{ + struct scmi_info *info = handle_to_scmi_info(handle); + struct scmi_protocol_instance *pi; + + mutex_lock(&info->protocols_mtx); + /* Ensure protocols has been updated */ + smp_rmb(); + pi = info->protocols[protocol_id]; + if (WARN_ON(!pi)) { + mutex_unlock(&info->protocols_mtx); + return; + } + + if (refcount_dec_and_test(&pi->users)) { + void *gid = pi->gid; + + if (pi->proto->deinit) + pi->proto->deinit(handle); + + info->protocols[protocol_id] = NULL; + /* Ensure deinitialized protocol is visible */ + smp_wmb(); + + devres_release_group(handle->dev, gid); + dev_dbg(handle->dev, "De-Initialized protocol: 0x%X\n", + protocol_id); + } + mutex_unlock(&info->protocols_mtx); +} + void scmi_setup_protocol_implemented(const struct scmi_handle *handle, u8 *prot_imp) { @@ -785,6 +934,7 @@ static int scmi_probe(struct platform_device *pdev) info->dev = dev; info->desc = desc; INIT_LIST_HEAD(&info->node); + mutex_init(&info->protocols_mtx); platform_set_drvdata(pdev, info); idr_init(&info->tx_idr); @@ -805,10 +955,14 @@ static int scmi_probe(struct platform_device *pdev) 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); - return ret; + /* + * Trigger SCMI Base protocol initialization. + * It's mandatory and won't be ever released/deinit until the + * SCMI stack is shutdown/unloaded as a whole. + */ + if (scmi_acquire_protocol(handle, SCMI_PROTOCOL_BASE)) { + dev_err(dev, "unable to communicate with SCMI\n"); + return -ENODEV; } mutex_lock(&scmi_list_mutex); @@ -941,6 +1095,8 @@ static int __init scmi_driver_init(void) { scmi_bus_init(); + scmi_base_register(); + scmi_clock_register(); scmi_perf_register(); scmi_power_register(); @@ -954,7 +1110,7 @@ subsys_initcall(scmi_driver_init); static void __exit scmi_driver_exit(void) { - scmi_bus_exit(); + scmi_base_unregister(); scmi_clock_unregister(); scmi_perf_unregister(); @@ -963,6 +1119,8 @@ static void __exit scmi_driver_exit(void) scmi_sensors_unregister(); scmi_system_unregister(); + scmi_bus_exit(); + platform_driver_unregister(&scmi_driver); } module_exit(scmi_driver_exit); diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c index c24e427dce0d..eae58b2a92cc 100644 --- a/drivers/firmware/arm_scmi/notify.c +++ b/drivers/firmware/arm_scmi/notify.c @@ -91,10 +91,9 @@ #include #include +#include "common.h" #include "notify.h" -#define SCMI_MAX_PROTO 256 - #define PROTO_ID_MASK GENMASK(31, 24) #define EVT_ID_MASK GENMASK(23, 16) #define SRC_ID_MASK GENMASK(15, 0) diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c index 82fb3babff72..854460a051c2 100644 --- a/drivers/firmware/arm_scmi/perf.c +++ b/drivers/firmware/arm_scmi/perf.c @@ -2,7 +2,7 @@ /* * System Control and Management Interface (SCMI) Performance Protocol * - * Copyright (C) 2018 ARM Ltd. + * Copyright (C) 2018-2020 ARM Ltd. */ #define pr_fmt(fmt) "SCMI Notifications PERF - " fmt @@ -892,4 +892,10 @@ static int scmi_perf_protocol_init(struct scmi_handle *handle) return 0; } -DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_PERF, perf) +static struct scmi_protocol scmi_perf = { + .id = SCMI_PROTOCOL_PERF, + .init = &scmi_perf_protocol_init, + .ops = &perf_ops, +}; + +DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(perf, scmi_perf) diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c index 1f37258e9bee..42c9c88da07c 100644 --- a/drivers/firmware/arm_scmi/power.c +++ b/drivers/firmware/arm_scmi/power.c @@ -2,7 +2,7 @@ /* * System Control and Management Interface (SCMI) Power Protocol * - * Copyright (C) 2018 ARM Ltd. + * Copyright (C) 2018-2020 ARM Ltd. */ #define pr_fmt(fmt) "SCMI Notifications POWER - " fmt @@ -301,4 +301,10 @@ static int scmi_power_protocol_init(struct scmi_handle *handle) return 0; } -DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_POWER, power) +static struct scmi_protocol scmi_power = { + .id = SCMI_PROTOCOL_POWER, + .init = &scmi_power_protocol_init, + .ops = &power_ops, +}; + +DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(power, scmi_power) diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c index a981a22cfe89..2caf0bdb6fdc 100644 --- a/drivers/firmware/arm_scmi/reset.c +++ b/drivers/firmware/arm_scmi/reset.c @@ -2,7 +2,7 @@ /* * System Control and Management Interface (SCMI) Reset Protocol * - * Copyright (C) 2019 ARM Ltd. + * Copyright (C) 2019-2020 ARM Ltd. */ #define pr_fmt(fmt) "SCMI Notifications RESET - " fmt @@ -311,4 +311,10 @@ static int scmi_reset_protocol_init(struct scmi_handle *handle) return 0; } -DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_RESET, reset) +static struct scmi_protocol scmi_reset = { + .id = SCMI_PROTOCOL_RESET, + .init = &scmi_reset_protocol_init, + .ops = &reset_ops, +}; + +DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(reset, scmi_reset) diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c index b4232d611033..dfe3076d2093 100644 --- a/drivers/firmware/arm_scmi/sensors.c +++ b/drivers/firmware/arm_scmi/sensors.c @@ -2,7 +2,7 @@ /* * System Control and Management Interface (SCMI) Sensor Protocol * - * Copyright (C) 2018 ARM Ltd. + * Copyright (C) 2018-2020 ARM Ltd. */ #define pr_fmt(fmt) "SCMI Notifications SENSOR - " fmt @@ -367,4 +367,10 @@ static int scmi_sensors_protocol_init(struct scmi_handle *handle) return 0; } -DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_SENSOR, sensors) +static struct scmi_protocol scmi_sensors = { + .id = SCMI_PROTOCOL_SENSOR, + .init = &scmi_sensors_protocol_init, + .ops = &sensor_ops, +}; + +DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(sensors, scmi_sensors) diff --git a/drivers/firmware/arm_scmi/system.c b/drivers/firmware/arm_scmi/system.c index 283e12d5f24b..bcea18bf54ab 100644 --- a/drivers/firmware/arm_scmi/system.c +++ b/drivers/firmware/arm_scmi/system.c @@ -128,4 +128,10 @@ static int scmi_system_protocol_init(struct scmi_handle *handle) return 0; } -DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_SYSTEM, system) +static struct scmi_protocol scmi_system = { + .id = SCMI_PROTOCOL_SYSTEM, + .init = &scmi_system_protocol_init, + .ops = NULL, +}; + +DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(system, scmi_system) diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 9cd312a1ff92..ca23d682941e 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -376,9 +376,9 @@ static inline void scmi_driver_unregister(struct scmi_driver *driver) {} #define module_scmi_driver(__scmi_driver) \ module_driver(__scmi_driver, scmi_register, scmi_unregister) -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); +struct scmi_protocol; +int scmi_protocol_register(struct scmi_protocol *proto); +void scmi_protocol_unregister(const struct scmi_protocol *proto); /* SCMI Notification API - Custom Event Reports */ enum scmi_notification_events { From patchwork Wed Oct 14 15:05:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11837849 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 C71A0921 for ; Wed, 14 Oct 2020 15:09:07 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (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 8398222201 for ; Wed, 14 Oct 2020 15:09:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="XdeTi3UK" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 8398222201 Authentication-Results: mail.kernel.org; dmarc=fail (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=merlin.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=zr0fCTzwOsrB05oLrpZRtOEB6gycVrR0V4gZt0H2ZVE=; b=XdeTi3UKAkSJqcpEsQPVXN4P/s QsPrLbiVNcAzDGk/0HHraFAIYbBs+/mzC8n+BlFn3RaZXu31wFuJys+c/EbS1zWh4ea5ME08oxIqD yLXHQJSmsSBQ5rEB0ruhrPflIhhvCiVqxp1WRLW6Wc1EdTXZb1ZK+MQk5HXFRJH3xYBIs2R1LLvRD oHMsk42AqZYLM7ENRZkG8P8pX0zrGD8Ko/XE4oqm3+hNsU4INwQyJ33Z2AmZ5oDgV2B2bd7Ko95ci vUkQbhzFTg0wx/OE7IhtOrMKWO6ER/63CxPcg6LbPpqS1CjDSfNMrQ8bXJpKqnDyQw2ntQhbugWgO NdUV9NKQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kSiMu-0001Lr-HP; Wed, 14 Oct 2020 15:07:08 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kSiMj-0001ID-Pr for linux-arm-kernel@lists.infradead.org; Wed, 14 Oct 2020 15:07:00 +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 424F513D5; Wed, 14 Oct 2020 08:06:57 -0700 (PDT) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 823703F71F; Wed, 14 Oct 2020 08:06:55 -0700 (PDT) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH 02/11] firmware: arm_scmi: hide protocols' private data Date: Wed, 14 Oct 2020 16:05:36 +0100 Message-Id: <20201014150545.44807-3-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201014150545.44807-1-cristian.marussi@arm.com> References: <20201014150545.44807-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201014_110658_008644_33ACC206 X-CRM114-Status: GOOD ( 19.11 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.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: f.fainelli@gmail.com, vincent.guittot@linaro.org, sudeep.holla@arm.com, thara.gopinath@linaro.org, cristian.marussi@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, souvik.chakravarty@arm.com, etienne.carriere@linaro.org, lukasz.luba@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 Protocols private data were meant to be used exclusively by protocol code but they are currently exposed through the handle, so available also to SCMI drivers: move them away from handle into instance specific data and provide internal helpers to let protocols implementation set/get their own private data from protocol code. Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/clock.c | 12 +++++----- drivers/firmware/arm_scmi/common.h | 4 ++++ drivers/firmware/arm_scmi/driver.c | 32 +++++++++++++++++++++++++++ drivers/firmware/arm_scmi/perf.c | 34 ++++++++++++++++++----------- drivers/firmware/arm_scmi/power.c | 10 ++++----- drivers/firmware/arm_scmi/reset.c | 16 ++++++++------ drivers/firmware/arm_scmi/sensors.c | 13 ++++++----- drivers/firmware/arm_scmi/system.c | 4 +--- include/linux/scmi_protocol.h | 17 --------------- 9 files changed, 86 insertions(+), 56 deletions(-) diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c index 94bcad9a7d19..4e8dafc36d7e 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -240,7 +240,8 @@ static int scmi_clock_rate_set(const struct scmi_handle *handle, u32 clk_id, u32 flags = 0; struct scmi_xfer *t; struct scmi_clock_set_rate *cfg; - struct clock_info *ci = handle->clk_priv; + struct clock_info *ci = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_CLOCK); ret = scmi_xfer_get_init(handle, CLOCK_RATE_SET, SCMI_PROTOCOL_CLOCK, sizeof(*cfg), 0, &t); @@ -303,7 +304,8 @@ static int scmi_clock_disable(const struct scmi_handle *handle, u32 clk_id) static int scmi_clock_count_get(const struct scmi_handle *handle) { - struct clock_info *ci = handle->clk_priv; + struct clock_info *ci = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_CLOCK); return ci->num_clocks; } @@ -311,7 +313,8 @@ static int scmi_clock_count_get(const struct scmi_handle *handle) static const struct scmi_clock_info * scmi_clock_info_get(const struct scmi_handle *handle, u32 clk_id) { - struct clock_info *ci = handle->clk_priv; + struct clock_info *ci = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_CLOCK); struct scmi_clock_info *clk = ci->clk + clk_id; if (!clk->name[0]) @@ -361,9 +364,8 @@ static int scmi_clock_protocol_init(struct scmi_handle *handle) cinfo->version = version; handle->clk_ops = &clk_ops; - handle->clk_priv = cinfo; - return 0; + return scmi_set_proto_priv(handle, SCMI_PROTOCOL_CLOCK, cinfo); } static struct scmi_protocol scmi_clock = { diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index b08a8ddbc22a..de2f22032a57 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -205,6 +205,10 @@ const struct scmi_protocol *scmi_get_protocol(int protocol_id); int scmi_acquire_protocol(struct scmi_handle *handle, u8 protocol_id); void scmi_release_protocol(struct scmi_handle *handle, u8 protocol_id); +void *scmi_get_proto_priv(const struct scmi_handle *h, u8 prot); +int scmi_set_proto_priv(const struct scmi_handle *handle, const u8 proto, + void *priv); + /* SCMI Transport */ /** * struct scmi_chan_info - Structure representing a SCMI channel information diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 7de994e49884..bad1d0130e96 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -100,6 +100,10 @@ struct scmi_protocol_instance { * this SCMI instance: populated on protocol's first attempted * usage. * @protocols_mtx: A mutex to protect protocols instances initialization. + * @protocols_private_data: An array of per-protocol per-instance private + * data: populated by protocol's initialization + * routines when @protocols is still not filled, so + * they have to sit on their own. * @protocols_imp: List of protocols implemented, currently maximum of * MAX_PROTOCOLS_IMP elements allocated by the base protocol * @node: List head @@ -117,6 +121,7 @@ struct scmi_info { struct scmi_protocol_instance *protocols[SCMI_MAX_PROTO]; /* Ensure mutual exclusive access to protocols instance array */ struct mutex protocols_mtx; + void *protocols_private_data[SCMI_MAX_PROTO]; u8 *protocols_imp; struct list_head node; int users; @@ -542,6 +547,32 @@ int scmi_version_get(const struct scmi_handle *handle, u8 protocol, return ret; } +int scmi_set_proto_priv(const struct scmi_handle *handle, + u8 protocol_id, void *priv) +{ + struct scmi_info *info = handle_to_scmi_info(handle); + + /* Ensure protocols_private_data has been updated */ + smp_rmb(); + if (WARN_ON(info->protocols_private_data[protocol_id])) + return -EINVAL; + + info->protocols_private_data[protocol_id] = priv; + /* Ensure updated protocol private date are visible */ + smp_wmb(); + + return 0; +} + +void *scmi_get_proto_priv(const struct scmi_handle *handle, u8 protocol_id) +{ + struct scmi_info *info = handle_to_scmi_info(handle); + + /* Ensure protocols_private_data has been updated */ + smp_rmb(); + return info->protocols_private_data[protocol_id]; +} + /** * scmi_get_protocol_instance - Protocol initialization helper. * @handle: A reference to the SCMI platform instance. @@ -657,6 +688,7 @@ void scmi_release_protocol(struct scmi_handle *handle, u8 protocol_id) if (pi->proto->deinit) pi->proto->deinit(handle); + info->protocols_private_data[protocol_id] = NULL; info->protocols[protocol_id] = NULL; /* Ensure deinitialized protocol is visible */ smp_wmb(); diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c index 854460a051c2..13e215f359fb 100644 --- a/drivers/firmware/arm_scmi/perf.c +++ b/drivers/firmware/arm_scmi/perf.c @@ -379,7 +379,8 @@ static int scmi_perf_mb_limits_set(const struct scmi_handle *handle, u32 domain, static int scmi_perf_limits_set(const struct scmi_handle *handle, u32 domain, u32 max_perf, u32 min_perf) { - struct scmi_perf_info *pi = handle->perf_priv; + struct scmi_perf_info *pi = scmi_get_proto_priv(handle, + SCMI_PROTOCOL_PERF); struct perf_dom_info *dom = pi->dom_info + domain; if (dom->fc_info && dom->fc_info->limit_set_addr) { @@ -421,7 +422,8 @@ static int scmi_perf_mb_limits_get(const struct scmi_handle *handle, u32 domain, static int scmi_perf_limits_get(const struct scmi_handle *handle, u32 domain, u32 *max_perf, u32 *min_perf) { - struct scmi_perf_info *pi = handle->perf_priv; + struct scmi_perf_info *pi = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_PERF); struct perf_dom_info *dom = pi->dom_info + domain; if (dom->fc_info && dom->fc_info->limit_get_addr) { @@ -459,7 +461,8 @@ static int scmi_perf_mb_level_set(const struct scmi_handle *handle, u32 domain, static int scmi_perf_level_set(const struct scmi_handle *handle, u32 domain, u32 level, bool poll) { - struct scmi_perf_info *pi = handle->perf_priv; + struct scmi_perf_info *pi = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_PERF); struct perf_dom_info *dom = pi->dom_info + domain; if (dom->fc_info && dom->fc_info->level_set_addr) { @@ -496,7 +499,8 @@ static int scmi_perf_mb_level_get(const struct scmi_handle *handle, u32 domain, static int scmi_perf_level_get(const struct scmi_handle *handle, u32 domain, u32 *level, bool poll) { - struct scmi_perf_info *pi = handle->perf_priv; + struct scmi_perf_info *pi = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_PERF); struct perf_dom_info *dom = pi->dom_info + domain; if (dom->fc_info && dom->fc_info->level_get_addr) { @@ -647,7 +651,8 @@ static int scmi_dvfs_device_opps_add(const struct scmi_handle *handle, unsigned long freq; struct scmi_opp *opp; struct perf_dom_info *dom; - struct scmi_perf_info *pi = handle->perf_priv; + struct scmi_perf_info *pi = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_PERF); domain = scmi_dev_domain_id(dev); if (domain < 0) @@ -676,7 +681,8 @@ static int scmi_dvfs_transition_latency_get(const struct scmi_handle *handle, struct device *dev) { struct perf_dom_info *dom; - struct scmi_perf_info *pi = handle->perf_priv; + struct scmi_perf_info *pi = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_PERF); int domain = scmi_dev_domain_id(dev); if (domain < 0) @@ -690,7 +696,8 @@ static int scmi_dvfs_transition_latency_get(const struct scmi_handle *handle, static int scmi_dvfs_freq_set(const struct scmi_handle *handle, u32 domain, unsigned long freq, bool poll) { - struct scmi_perf_info *pi = handle->perf_priv; + struct scmi_perf_info *pi = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_PERF); struct perf_dom_info *dom = pi->dom_info + domain; return scmi_perf_level_set(handle, domain, freq / dom->mult_factor, @@ -702,7 +709,8 @@ static int scmi_dvfs_freq_get(const struct scmi_handle *handle, u32 domain, { int ret; u32 level; - struct scmi_perf_info *pi = handle->perf_priv; + struct scmi_perf_info *pi = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_PERF); struct perf_dom_info *dom = pi->dom_info + domain; ret = scmi_perf_level_get(handle, domain, &level, poll); @@ -715,7 +723,8 @@ static int scmi_dvfs_freq_get(const struct scmi_handle *handle, u32 domain, static int scmi_dvfs_est_power_get(const struct scmi_handle *handle, u32 domain, unsigned long *freq, unsigned long *power) { - struct scmi_perf_info *pi = handle->perf_priv; + struct scmi_perf_info *pi = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_PERF); struct perf_dom_info *dom; unsigned long opp_freq; int idx, ret = -EINVAL; @@ -743,7 +752,8 @@ static bool scmi_fast_switch_possible(const struct scmi_handle *handle, struct device *dev) { struct perf_dom_info *dom; - struct scmi_perf_info *pi = handle->perf_priv; + struct scmi_perf_info *pi = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_PERF); dom = pi->dom_info + scmi_dev_domain_id(dev); @@ -887,9 +897,7 @@ static int scmi_perf_protocol_init(struct scmi_handle *handle) pinfo->version = version; handle->perf_ops = &perf_ops; - handle->perf_priv = pinfo; - - return 0; + return scmi_set_proto_priv(handle, SCMI_PROTOCOL_PERF, pinfo); } static struct scmi_protocol scmi_perf = { diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c index 42c9c88da07c..e0b29ed4e09a 100644 --- a/drivers/firmware/arm_scmi/power.c +++ b/drivers/firmware/arm_scmi/power.c @@ -171,14 +171,16 @@ scmi_power_state_get(const struct scmi_handle *handle, u32 domain, u32 *state) static int scmi_power_num_domains_get(const struct scmi_handle *handle) { - struct scmi_power_info *pi = handle->power_priv; + struct scmi_power_info *pi = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_POWER); return pi->num_domains; } static char *scmi_power_name_get(const struct scmi_handle *handle, u32 domain) { - struct scmi_power_info *pi = handle->power_priv; + struct scmi_power_info *pi = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_POWER); struct power_dom_info *dom = pi->dom_info + domain; return dom->name; @@ -296,9 +298,7 @@ static int scmi_power_protocol_init(struct scmi_handle *handle) pinfo->version = version; handle->power_ops = &power_ops; - handle->power_priv = pinfo; - - return 0; + return scmi_set_proto_priv(handle, SCMI_PROTOCOL_POWER, pinfo); } static struct scmi_protocol scmi_power = { diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c index 2caf0bdb6fdc..f70e9b5108d5 100644 --- a/drivers/firmware/arm_scmi/reset.c +++ b/drivers/firmware/arm_scmi/reset.c @@ -121,14 +121,16 @@ scmi_reset_domain_attributes_get(const struct scmi_handle *handle, u32 domain, static int scmi_reset_num_domains_get(const struct scmi_handle *handle) { - struct scmi_reset_info *pi = handle->reset_priv; + struct scmi_reset_info *pi = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_RESET); return pi->num_domains; } static char *scmi_reset_name_get(const struct scmi_handle *handle, u32 domain) { - struct scmi_reset_info *pi = handle->reset_priv; + struct scmi_reset_info *pi = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_RESET); struct reset_dom_info *dom = pi->dom_info + domain; return dom->name; @@ -136,7 +138,8 @@ static char *scmi_reset_name_get(const struct scmi_handle *handle, u32 domain) static int scmi_reset_latency_get(const struct scmi_handle *handle, u32 domain) { - struct scmi_reset_info *pi = handle->reset_priv; + struct scmi_reset_info *pi = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_RESET); struct reset_dom_info *dom = pi->dom_info + domain; return dom->latency_us; @@ -148,7 +151,8 @@ static int scmi_domain_reset(const struct scmi_handle *handle, u32 domain, int ret; struct scmi_xfer *t; struct scmi_msg_reset_domain_reset *dom; - struct scmi_reset_info *pi = handle->reset_priv; + struct scmi_reset_info *pi = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_RESET); struct reset_dom_info *rdom = pi->dom_info + domain; if (rdom->async_reset) @@ -306,9 +310,7 @@ static int scmi_reset_protocol_init(struct scmi_handle *handle) pinfo->version = version; handle->reset_ops = &reset_ops; - handle->reset_priv = pinfo; - - return 0; + return scmi_set_proto_priv(handle, SCMI_PROTOCOL_RESET, pinfo); } static struct scmi_protocol scmi_reset = { diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c index dfe3076d2093..8a0a599558ba 100644 --- a/drivers/firmware/arm_scmi/sensors.c +++ b/drivers/firmware/arm_scmi/sensors.c @@ -233,7 +233,8 @@ static int scmi_sensor_reading_get(const struct scmi_handle *handle, int ret; struct scmi_xfer *t; struct scmi_msg_sensor_reading_get *sensor; - struct sensors_info *si = handle->sensor_priv; + struct sensors_info *si = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_SENSOR); struct scmi_sensor_info *s = si->sensors + sensor_id; ret = scmi_xfer_get_init(handle, SENSOR_READING_GET, @@ -265,14 +266,16 @@ static int scmi_sensor_reading_get(const struct scmi_handle *handle, static const struct scmi_sensor_info * scmi_sensor_info_get(const struct scmi_handle *handle, u32 sensor_id) { - struct sensors_info *si = handle->sensor_priv; + struct sensors_info *si = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_SENSOR); return si->sensors + sensor_id; } static int scmi_sensor_count_get(const struct scmi_handle *handle) { - struct sensors_info *si = handle->sensor_priv; + struct sensors_info *si = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_SENSOR); return si->num_sensors; } @@ -362,9 +365,7 @@ static int scmi_sensors_protocol_init(struct scmi_handle *handle) sinfo->version = version; handle->sensor_ops = &sensor_ops; - handle->sensor_priv = sinfo; - - return 0; + return scmi_set_proto_priv(handle, SCMI_PROTOCOL_SENSOR, sinfo); } static struct scmi_protocol scmi_sensors = { diff --git a/drivers/firmware/arm_scmi/system.c b/drivers/firmware/arm_scmi/system.c index bcea18bf54ab..8f53f93c63ca 100644 --- a/drivers/firmware/arm_scmi/system.c +++ b/drivers/firmware/arm_scmi/system.c @@ -123,9 +123,7 @@ static int scmi_system_protocol_init(struct scmi_handle *handle) SCMI_SYSTEM_NUM_SOURCES); pinfo->version = version; - handle->system_priv = pinfo; - - return 0; + return scmi_set_proto_priv(handle, SCMI_PROTOCOL_SYSTEM, pinfo); } static struct scmi_protocol scmi_system = { diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index ca23d682941e..bc4f06d46bfb 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -263,16 +263,6 @@ struct scmi_notify_ops { * @sensor_ops: pointer to set of sensor protocol operations * @reset_ops: pointer to set of reset protocol operations * @notify_ops: pointer to set of notifications related operations - * @perf_priv: pointer to private data structure specific to performance - * protocol(for internal use only) - * @clk_priv: pointer to private data structure specific to clock - * protocol(for internal use only) - * @power_priv: pointer to private data structure specific to power - * protocol(for internal use only) - * @sensor_priv: pointer to private data structure specific to sensors - * protocol(for internal use only) - * @reset_priv: pointer to private data structure specific to reset - * protocol(for internal use only) * @notify_priv: pointer to private data structure specific to notifications * (for internal use only) */ @@ -285,14 +275,7 @@ struct scmi_handle { const struct scmi_sensor_ops *sensor_ops; const struct scmi_reset_ops *reset_ops; const struct scmi_notify_ops *notify_ops; - /* for protocol internal use */ - void *perf_priv; - void *clk_priv; - void *power_priv; - void *sensor_priv; - void *reset_priv; void *notify_priv; - void *system_priv; }; enum scmi_std_protocol { From patchwork Wed Oct 14 15:05:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11837835 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 0E958921 for ; Wed, 14 Oct 2020 15:07:30 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (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 C682221582 for ; Wed, 14 Oct 2020 15:07:29 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="aU4hrIfx" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C682221582 Authentication-Results: mail.kernel.org; dmarc=fail (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=merlin.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=Z+Posy4ef6OreIPYkNGEWPI8bjePzzP4iXDA+wtkCr8=; b=aU4hrIfxwVW73g7sfKGrHq6PsB bU2aggOvxW4RMcsmEnfTthHk30XJsRSo9/Qtw5YOT9yOE6bmXxawDwpwWEiW1cT6ou/ikgsm3kpHi TpfIQztDOMinXsHs+Qo+4jAPSknRhteTv/b6tLxcicFQRQrs6OP9Tu0M/YW8PdRWFYpwhiJvWvThE 4DVvshwUIvwx9M0b406HIj8q8Y2XGA+lFsYo7pxrynEqE0PAdPnQMFGrnp8HuSpB+3yglup31gi/1 NmsLdp6/iFD9AVrHEthVhNv8JZbIEtLEwHZLDzs0Udz6jsA7R72hRtd3tIXZAK/LFNI7VM4tHLLiQ YarzqrFg==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kSiN0-0001OW-RF; Wed, 14 Oct 2020 15:07:14 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kSiMl-0001If-Dk for linux-arm-kernel@lists.infradead.org; Wed, 14 Oct 2020 15:07:02 +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 1D4CC1435; Wed, 14 Oct 2020 08:06:59 -0700 (PDT) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 793DA3F71F; Wed, 14 Oct 2020 08:06:57 -0700 (PDT) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH 03/11] firmware: arm_scmi: introduce common protocol interface Date: Wed, 14 Oct 2020 16:05:37 +0100 Message-Id: <20201014150545.44807-4-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201014150545.44807-1-cristian.marussi@arm.com> References: <20201014150545.44807-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201014_110659_639551_84DBFA0A X-CRM114-Status: GOOD ( 26.74 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.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: f.fainelli@gmail.com, vincent.guittot@linaro.org, sudeep.holla@arm.com, thara.gopinath@linaro.org, cristian.marussi@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, souvik.chakravarty@arm.com, etienne.carriere@linaro.org, lukasz.luba@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 Introduce generic get_ops/put_ops handle operations: any protocol, both standard or custom, now exposes its operations through this common interface which internally takes care to account for protocols' usage: protocols' initialization is now performed on demand as soon as the first user shows up while deinitialization (if any) is performed once the last user of a protocol has gone. Registered events' notifier are tracked too against the related protocol. Convert all SCMI drivers to the new interface too. Signed-off-by: Cristian Marussi --- drivers/clk/clk-scmi.c | 30 +++++++++---- drivers/cpufreq/scmi-cpufreq.c | 28 ++++++------ drivers/firmware/arm_scmi/base.c | 2 +- drivers/firmware/arm_scmi/bus.c | 24 ----------- drivers/firmware/arm_scmi/clock.c | 4 +- drivers/firmware/arm_scmi/common.h | 6 +-- drivers/firmware/arm_scmi/driver.c | 31 ++++++++++++-- drivers/firmware/arm_scmi/notify.c | 50 +++++++++++++++++++--- drivers/firmware/arm_scmi/perf.c | 3 +- drivers/firmware/arm_scmi/power.c | 3 +- drivers/firmware/arm_scmi/reset.c | 3 +- drivers/firmware/arm_scmi/scmi_pm_domain.c | 29 +++++++++---- drivers/firmware/arm_scmi/sensors.c | 3 +- drivers/firmware/arm_scmi/system.c | 2 +- drivers/hwmon/scmi-hwmon.c | 26 ++++++++--- drivers/reset/reset-scmi.c | 26 ++++++++--- include/linux/scmi_protocol.h | 15 +++---- 17 files changed, 185 insertions(+), 100 deletions(-) diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c index c754dfbb73fd..4801a2df044b 100644 --- a/drivers/clk/clk-scmi.c +++ b/drivers/clk/clk-scmi.c @@ -2,7 +2,7 @@ /* * System Control and Power Interface (SCMI) Protocol based clock driver * - * Copyright (C) 2018 ARM Ltd. + * Copyright (C) 2018-2020 ARM Ltd. */ #include @@ -13,6 +13,8 @@ #include #include +static const struct scmi_clk_ops *clk_ops; + struct scmi_clk { u32 id; struct clk_hw hw; @@ -29,7 +31,7 @@ static unsigned long scmi_clk_recalc_rate(struct clk_hw *hw, u64 rate; struct scmi_clk *clk = to_scmi_clk(hw); - ret = clk->handle->clk_ops->rate_get(clk->handle, clk->id, &rate); + ret = clk_ops->rate_get(clk->handle, clk->id, &rate); if (ret) return 0; return rate; @@ -69,21 +71,21 @@ static int scmi_clk_set_rate(struct clk_hw *hw, unsigned long rate, { struct scmi_clk *clk = to_scmi_clk(hw); - return clk->handle->clk_ops->rate_set(clk->handle, clk->id, rate); + return clk_ops->rate_set(clk->handle, clk->id, rate); } static int scmi_clk_enable(struct clk_hw *hw) { struct scmi_clk *clk = to_scmi_clk(hw); - return clk->handle->clk_ops->enable(clk->handle, clk->id); + return clk_ops->enable(clk->handle, clk->id); } static void scmi_clk_disable(struct clk_hw *hw) { struct scmi_clk *clk = to_scmi_clk(hw); - clk->handle->clk_ops->disable(clk->handle, clk->id); + clk_ops->disable(clk->handle, clk->id); } static const struct clk_ops scmi_clk_ops = { @@ -143,10 +145,14 @@ static int scmi_clocks_probe(struct scmi_device *sdev) struct device_node *np = dev->of_node; const struct scmi_handle *handle = sdev->handle; - if (!handle || !handle->clk_ops) + if (!handle) return -ENODEV; - count = handle->clk_ops->count_get(handle); + clk_ops = handle->get_ops(handle, SCMI_PROTOCOL_CLOCK); + if (IS_ERR(clk_ops)) + return PTR_ERR(clk_ops); + + count = clk_ops->count_get(handle); if (count < 0) { dev_err(dev, "%pOFn: invalid clock output count\n", np); return -EINVAL; @@ -167,7 +173,7 @@ static int scmi_clocks_probe(struct scmi_device *sdev) if (!sclk) return -ENOMEM; - sclk->info = handle->clk_ops->info_get(handle, idx); + sclk->info = clk_ops->info_get(handle, idx); if (!sclk->info) { dev_dbg(dev, "invalid clock info for idx %d\n", idx); continue; @@ -191,6 +197,13 @@ static int scmi_clocks_probe(struct scmi_device *sdev) clk_data); } +static void scmi_clocks_remove(struct scmi_device *sdev) +{ + const struct scmi_handle *handle = sdev->handle; + + handle->put_ops(handle, SCMI_PROTOCOL_CLOCK); +} + static const struct scmi_device_id scmi_id_table[] = { { SCMI_PROTOCOL_CLOCK, "clocks" }, { }, @@ -200,6 +213,7 @@ MODULE_DEVICE_TABLE(scmi, scmi_id_table); static struct scmi_driver scmi_clocks_driver = { .name = "scmi-clocks", .probe = scmi_clocks_probe, + .remove = scmi_clocks_remove, .id_table = scmi_id_table, }; module_scmi_driver(scmi_clocks_driver); diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c index 46b268095421..280597b3c6fd 100644 --- a/drivers/cpufreq/scmi-cpufreq.c +++ b/drivers/cpufreq/scmi-cpufreq.c @@ -25,11 +25,11 @@ struct scmi_data { }; static const struct scmi_handle *handle; +static const struct scmi_perf_ops *perf_ops; static unsigned int scmi_cpufreq_get_rate(unsigned int cpu) { struct cpufreq_policy *policy = cpufreq_cpu_get_raw(cpu); - const struct scmi_perf_ops *perf_ops = handle->perf_ops; struct scmi_data *priv = policy->driver_data; unsigned long rate; int ret; @@ -50,7 +50,6 @@ scmi_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index) { int ret; struct scmi_data *priv = policy->driver_data; - const struct scmi_perf_ops *perf_ops = handle->perf_ops; u64 freq = policy->freq_table[index].frequency; ret = perf_ops->freq_set(handle, priv->domain_id, freq * 1000, false); @@ -64,7 +63,6 @@ static unsigned int scmi_cpufreq_fast_switch(struct cpufreq_policy *policy, unsigned int target_freq) { struct scmi_data *priv = policy->driver_data; - const struct scmi_perf_ops *perf_ops = handle->perf_ops; if (!perf_ops->freq_set(handle, priv->domain_id, target_freq * 1000, true)) { @@ -82,7 +80,7 @@ scmi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask) int cpu, domain, tdomain; struct device *tcpu_dev; - domain = handle->perf_ops->device_domain_id(cpu_dev); + domain = perf_ops->device_domain_id(cpu_dev); if (domain < 0) return domain; @@ -94,7 +92,7 @@ scmi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask) if (!tcpu_dev) continue; - tdomain = handle->perf_ops->device_domain_id(tcpu_dev); + tdomain = perf_ops->device_domain_id(tcpu_dev); if (tdomain == domain) cpumask_set_cpu(cpu, cpumask); } @@ -109,13 +107,13 @@ scmi_get_cpu_power(unsigned long *power, unsigned long *KHz, unsigned long Hz; int ret, domain; - domain = handle->perf_ops->device_domain_id(cpu_dev); + domain = perf_ops->device_domain_id(cpu_dev); if (domain < 0) return domain; /* Get the power cost of the performance domain. */ Hz = *KHz * 1000; - ret = handle->perf_ops->est_power_get(handle, domain, &Hz, power); + ret = perf_ops->est_power_get(handle, domain, &Hz, power); if (ret) return ret; @@ -140,7 +138,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy) return -ENODEV; } - ret = handle->perf_ops->device_opps_add(handle, cpu_dev); + ret = perf_ops->device_opps_add(handle, cpu_dev); if (ret) { dev_warn(cpu_dev, "failed to add opps to the device\n"); return ret; @@ -179,7 +177,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy) } priv->cpu_dev = cpu_dev; - priv->domain_id = handle->perf_ops->device_domain_id(cpu_dev); + priv->domain_id = perf_ops->device_domain_id(cpu_dev); policy->driver_data = priv; policy->freq_table = freq_table; @@ -187,14 +185,14 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy) /* SCMI allows DVFS request for any domain from any CPU */ policy->dvfs_possible_from_any_cpu = true; - latency = handle->perf_ops->transition_latency_get(handle, cpu_dev); + latency = perf_ops->transition_latency_get(handle, cpu_dev); if (!latency) latency = CPUFREQ_ETERNAL; policy->cpuinfo.transition_latency = latency; policy->fast_switch_possible = - handle->perf_ops->fast_switch_possible(handle, cpu_dev); + perf_ops->fast_switch_possible(handle, cpu_dev); em_dev_register_perf_domain(cpu_dev, nr_opp, &em_cb, policy->cpus); @@ -239,9 +237,13 @@ static int scmi_cpufreq_probe(struct scmi_device *sdev) handle = sdev->handle; - if (!handle || !handle->perf_ops) + if (!handle) return -ENODEV; + perf_ops = handle->get_ops(handle, SCMI_PROTOCOL_PERF); + if (IS_ERR(perf_ops)) + return PTR_ERR(perf_ops); + ret = cpufreq_register_driver(&scmi_cpufreq_driver); if (ret) { dev_err(&sdev->dev, "%s: registering cpufreq failed, err: %d\n", @@ -254,6 +256,8 @@ static int scmi_cpufreq_probe(struct scmi_device *sdev) static void scmi_cpufreq_remove(struct scmi_device *sdev) { cpufreq_unregister_driver(&scmi_cpufreq_driver); + + handle->put_ops(handle, SCMI_PROTOCOL_PERF); } static const struct scmi_device_id scmi_id_table[] = { diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c index f19e08ed4369..129633e6fff4 100644 --- a/drivers/firmware/arm_scmi/base.c +++ b/drivers/firmware/arm_scmi/base.c @@ -318,7 +318,7 @@ static const struct scmi_event_ops base_event_ops = { .fill_custom_report = scmi_base_fill_custom_report, }; -static int scmi_base_protocol_init(struct scmi_handle *h) +static int scmi_base_protocol_init(const struct scmi_handle *h) { int id, ret; u8 *prot_imp; diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c index afa2e4818a2b..3a2be1193c85 100644 --- a/drivers/firmware/arm_scmi/bus.c +++ b/drivers/firmware/arm_scmi/bus.c @@ -66,27 +66,11 @@ const struct scmi_protocol *scmi_get_protocol(int protocol_id) return proto; } -static int scmi_protocol_init(int protocol_id, struct scmi_handle *handle) -{ - const struct scmi_protocol *proto; - - proto = idr_find(&scmi_available_protocols, protocol_id); - if (!proto) - return -EINVAL; - return proto->init(handle); -} - -static int scmi_protocol_dummy_init(struct scmi_handle *handle) -{ - return 0; -} - static int scmi_dev_probe(struct device *dev) { struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver); struct scmi_device *scmi_dev = to_scmi_dev(dev); const struct scmi_device_id *id; - int ret; id = scmi_dev_match_id(scmi_dev, scmi_drv); if (!id) @@ -95,14 +79,6 @@ static int scmi_dev_probe(struct device *dev) if (!scmi_dev->handle) return -EPROBE_DEFER; - ret = scmi_protocol_init(scmi_dev->protocol_id, scmi_dev->handle); - if (ret) - return ret; - - /* Skip protocol initialisation for additional devices */ - idr_replace(&scmi_available_protocols, &scmi_protocol_dummy_init, - scmi_dev->protocol_id); - return scmi_drv->probe(scmi_dev); } diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c index 4e8dafc36d7e..539c94860b8f 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -332,7 +332,7 @@ static const struct scmi_clk_ops clk_ops = { .disable = scmi_clock_disable, }; -static int scmi_clock_protocol_init(struct scmi_handle *handle) +static int scmi_clock_protocol_init(const struct scmi_handle *handle) { u32 version; int clkid, ret; @@ -363,8 +363,6 @@ static int scmi_clock_protocol_init(struct scmi_handle *handle) } cinfo->version = version; - handle->clk_ops = &clk_ops; - return scmi_set_proto_priv(handle, SCMI_PROTOCOL_CLOCK, cinfo); } diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index de2f22032a57..56ebb710ee84 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -158,7 +158,7 @@ int scmi_version_get(const struct scmi_handle *h, u8 protocol, u32 *version); void scmi_setup_protocol_implemented(const struct scmi_handle *handle, u8 *prot_imp); -typedef int (*scmi_prot_init_fn_t)(struct scmi_handle *); +typedef int (*scmi_prot_init_fn_t)(const struct scmi_handle *); /** * struct scmi_protocol - Protocol descriptor @@ -202,8 +202,8 @@ void __exit scmi_##name##_unregister(void) \ const struct scmi_protocol *scmi_get_protocol(int protocol_id); -int scmi_acquire_protocol(struct scmi_handle *handle, u8 protocol_id); -void scmi_release_protocol(struct scmi_handle *handle, u8 protocol_id); +int scmi_acquire_protocol(const struct scmi_handle *handle, u8 protocol_id); +void scmi_release_protocol(const struct scmi_handle *handle, u8 protocol_id); void *scmi_get_proto_priv(const struct scmi_handle *h, u8 prot); int scmi_set_proto_priv(const struct scmi_handle *handle, const u8 proto, diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index bad1d0130e96..049220efd227 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -585,7 +585,7 @@ void *scmi_get_proto_priv(const struct scmi_handle *handle, u8 protocol_id) * Return: A reference to an initialized protocol instance or error on failure. */ static struct scmi_protocol_instance * __must_check -scmi_get_protocol_instance(struct scmi_handle *handle, u8 protocol_id) +scmi_get_protocol_instance(const struct scmi_handle *handle, u8 protocol_id) { int ret = -ENOMEM; void *gid; @@ -655,7 +655,7 @@ scmi_get_protocol_instance(struct scmi_handle *handle, u8 protocol_id) * * Return: 0 if protocol was acquired successfully. */ -int scmi_acquire_protocol(struct scmi_handle *handle, u8 protocol_id) +int scmi_acquire_protocol(const struct scmi_handle *handle, u8 protocol_id) { return IS_ERR(scmi_get_protocol_instance(handle, protocol_id)); } @@ -668,7 +668,7 @@ int scmi_acquire_protocol(struct scmi_handle *handle, u8 protocol_id) * Remove one user for the specified protocol and triggers de-initialization * and resources de-allocation once the last user has gone. */ -void scmi_release_protocol(struct scmi_handle *handle, u8 protocol_id) +void scmi_release_protocol(const struct scmi_handle *handle, u8 protocol_id) { struct scmi_info *info = handle_to_scmi_info(handle); struct scmi_protocol_instance *pi; @@ -700,6 +700,29 @@ void scmi_release_protocol(struct scmi_handle *handle, u8 protocol_id) mutex_unlock(&info->protocols_mtx); } +/** + * scmi_get_protocol_operations - Get protocol operations + * @handle: A reference to the SCMI platform instance. + * @protocol_id: The protocol being requested. + * + * Get hold of a protocol accounting for its usage, eventually triggering its + * initialization, and returning the protocol specific operations. + * + * Return: A reference to the requested protocol operations or error. + * Must be checked for errors by caller. + */ +static const void __must_check +*scmi_get_protocol_operations(const struct scmi_handle *handle, u8 protocol_id) +{ + struct scmi_protocol_instance *pi; + + pi = scmi_get_protocol_instance(handle, protocol_id); + if (IS_ERR(pi)) + return pi; + + return pi->proto->ops; +} + void scmi_setup_protocol_implemented(const struct scmi_handle *handle, u8 *prot_imp) { @@ -975,6 +998,8 @@ static int scmi_probe(struct platform_device *pdev) handle = &info->handle; handle->dev = info->dev; handle->version = &info->version; + handle->get_ops = scmi_get_protocol_operations; + handle->put_ops = scmi_release_protocol; ret = scmi_txrx_setup(info, dev, SCMI_PROTOCOL_BASE); if (ret) diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c index eae58b2a92cc..02b00af9b08f 100644 --- a/drivers/firmware/arm_scmi/notify.c +++ b/drivers/firmware/arm_scmi/notify.c @@ -367,7 +367,7 @@ static struct scmi_event_handler * scmi_get_active_handler(struct scmi_notify_instance *ni, u32 evt_key); static void scmi_put_active_handler(struct scmi_notify_instance *ni, struct scmi_event_handler *hndl); -static void scmi_put_handler_unlocked(struct scmi_notify_instance *ni, +static bool scmi_put_handler_unlocked(struct scmi_notify_instance *ni, struct scmi_event_handler *hndl); /** @@ -899,9 +899,21 @@ static inline int scmi_bind_event_handler(struct scmi_notify_instance *ni, if (!r_evt) return -EINVAL; - /* Remove from pending and insert into registered */ + /* + * Remove from pending and insert into registered while getting hold + * of protocol instance. + */ hash_del(&hndl->hash); + /* + * Acquire protocols only for NON pending handlers, so as NOT to trigger + * protocol initialization when a notifier is registered against a still + * not registered protocol, since it would make little sense to force init + * protocols for which still no SCMI driver user exists: they wouldn't + * emit any event anyway till some SCMI driver starts using it. + */ + scmi_acquire_protocol(ni->handle, KEY_XTRACT_PROTO_ID(hndl->key)); hndl->r_evt = r_evt; + mutex_lock(&r_evt->proto->registered_mtx); hash_add(r_evt->proto->registered_events_handlers, &hndl->hash, hndl->key); @@ -1192,41 +1204,65 @@ static int scmi_disable_events(struct scmi_event_handler *hndl) * * unregister and free the handler itself * * Context: Assumes all the proper locking has been managed by the caller. + * + * Return: True if handler was freed (users dropped to zero) */ -static void scmi_put_handler_unlocked(struct scmi_notify_instance *ni, +static bool scmi_put_handler_unlocked(struct scmi_notify_instance *ni, struct scmi_event_handler *hndl) { + bool freed = false; + if (refcount_dec_and_test(&hndl->users)) { if (!IS_HNDL_PENDING(hndl)) scmi_disable_events(hndl); scmi_free_event_handler(hndl); + freed = true; } + + return freed; } static void scmi_put_handler(struct scmi_notify_instance *ni, struct scmi_event_handler *hndl) { + bool freed; + u8 protocol_id; struct scmi_registered_event *r_evt = hndl->r_evt; mutex_lock(&ni->pending_mtx); - if (r_evt) + if (r_evt) { + protocol_id = r_evt->proto->id; mutex_lock(&r_evt->proto->registered_mtx); + } - scmi_put_handler_unlocked(ni, hndl); + freed = scmi_put_handler_unlocked(ni, hndl); - if (r_evt) + if (r_evt) { mutex_unlock(&r_evt->proto->registered_mtx); + /* + * Only registered handler acquired protocol; must be here + * released only AFTER unlocking registered_mtx, since + * releasing a protocol can trigger its de-initialization + * (ie. including r_evt and registered_mtx) + */ + if (freed) + scmi_release_protocol(ni->handle, protocol_id); + } mutex_unlock(&ni->pending_mtx); } static void scmi_put_active_handler(struct scmi_notify_instance *ni, struct scmi_event_handler *hndl) { + bool freed; struct scmi_registered_event *r_evt = hndl->r_evt; + u8 protocol_id = r_evt->proto->id; mutex_lock(&r_evt->proto->registered_mtx); - scmi_put_handler_unlocked(ni, hndl); + freed = scmi_put_handler_unlocked(ni, hndl); mutex_unlock(&r_evt->proto->registered_mtx); + if (freed) + scmi_release_protocol(ni->handle, protocol_id); } /** diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c index 13e215f359fb..bd9cb2583557 100644 --- a/drivers/firmware/arm_scmi/perf.c +++ b/drivers/firmware/arm_scmi/perf.c @@ -857,7 +857,7 @@ static const struct scmi_event_ops perf_event_ops = { .fill_custom_report = scmi_perf_fill_custom_report, }; -static int scmi_perf_protocol_init(struct scmi_handle *handle) +static int scmi_perf_protocol_init(const struct scmi_handle *handle) { int domain; u32 version; @@ -896,7 +896,6 @@ static int scmi_perf_protocol_init(struct scmi_handle *handle) pinfo->num_domains); pinfo->version = version; - handle->perf_ops = &perf_ops; return scmi_set_proto_priv(handle, SCMI_PROTOCOL_PERF, pinfo); } diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c index e0b29ed4e09a..1e026b5530a7 100644 --- a/drivers/firmware/arm_scmi/power.c +++ b/drivers/firmware/arm_scmi/power.c @@ -262,7 +262,7 @@ static const struct scmi_event_ops power_event_ops = { .fill_custom_report = scmi_power_fill_custom_report, }; -static int scmi_power_protocol_init(struct scmi_handle *handle) +static int scmi_power_protocol_init(const struct scmi_handle *handle) { int domain; u32 version; @@ -297,7 +297,6 @@ static int scmi_power_protocol_init(struct scmi_handle *handle) pinfo->num_domains); pinfo->version = version; - handle->power_ops = &power_ops; return scmi_set_proto_priv(handle, SCMI_PROTOCOL_POWER, pinfo); } diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c index f70e9b5108d5..b7da4de0e56e 100644 --- a/drivers/firmware/arm_scmi/reset.c +++ b/drivers/firmware/arm_scmi/reset.c @@ -274,7 +274,7 @@ static const struct scmi_event_ops reset_event_ops = { .fill_custom_report = scmi_reset_fill_custom_report, }; -static int scmi_reset_protocol_init(struct scmi_handle *handle) +static int scmi_reset_protocol_init(const struct scmi_handle *handle) { int domain; u32 version; @@ -309,7 +309,6 @@ static int scmi_reset_protocol_init(struct scmi_handle *handle) pinfo->num_domains); pinfo->version = version; - handle->reset_ops = &reset_ops; return scmi_set_proto_priv(handle, SCMI_PROTOCOL_RESET, pinfo); } diff --git a/drivers/firmware/arm_scmi/scmi_pm_domain.c b/drivers/firmware/arm_scmi/scmi_pm_domain.c index 9e44479f0284..bfea56f77890 100644 --- a/drivers/firmware/arm_scmi/scmi_pm_domain.c +++ b/drivers/firmware/arm_scmi/scmi_pm_domain.c @@ -2,7 +2,7 @@ /* * SCMI Generic power domain support. * - * Copyright (C) 2018 ARM Ltd. + * Copyright (C) 2018-2020 ARM Ltd. */ #include @@ -11,6 +11,8 @@ #include #include +static const struct scmi_power_ops *power_ops; + struct scmi_pm_domain { struct generic_pm_domain genpd; const struct scmi_handle *handle; @@ -25,16 +27,15 @@ static int scmi_pd_power(struct generic_pm_domain *domain, bool power_on) int ret; u32 state, ret_state; struct scmi_pm_domain *pd = to_scmi_pd(domain); - const struct scmi_power_ops *ops = pd->handle->power_ops; if (power_on) state = SCMI_POWER_STATE_GENERIC_ON; else state = SCMI_POWER_STATE_GENERIC_OFF; - ret = ops->state_set(pd->handle, pd->domain, state); + ret = power_ops->state_set(pd->handle, pd->domain, state); if (!ret) - ret = ops->state_get(pd->handle, pd->domain, &ret_state); + ret = power_ops->state_get(pd->handle, pd->domain, &ret_state); if (!ret && state != ret_state) return -EIO; @@ -61,10 +62,14 @@ static int scmi_pm_domain_probe(struct scmi_device *sdev) struct generic_pm_domain **domains; const struct scmi_handle *handle = sdev->handle; - if (!handle || !handle->power_ops) + if (!handle) return -ENODEV; - num_domains = handle->power_ops->num_domains_get(handle); + power_ops = handle->get_ops(handle, SCMI_PROTOCOL_POWER); + if (IS_ERR(power_ops)) + return PTR_ERR(power_ops); + + num_domains = power_ops->num_domains_get(handle); if (num_domains < 0) { dev_err(dev, "number of domains not found\n"); return num_domains; @@ -85,14 +90,14 @@ static int scmi_pm_domain_probe(struct scmi_device *sdev) for (i = 0; i < num_domains; i++, scmi_pd++) { u32 state; - if (handle->power_ops->state_get(handle, i, &state)) { + if (power_ops->state_get(handle, i, &state)) { dev_warn(dev, "failed to get state for domain %d\n", i); continue; } scmi_pd->domain = i; scmi_pd->handle = handle; - scmi_pd->name = handle->power_ops->name_get(handle, i); + scmi_pd->name = power_ops->name_get(handle, i); scmi_pd->genpd.name = scmi_pd->name; scmi_pd->genpd.power_off = scmi_pd_power_off; scmi_pd->genpd.power_on = scmi_pd_power_on; @@ -111,6 +116,13 @@ static int scmi_pm_domain_probe(struct scmi_device *sdev) return 0; } +static void scmi_pm_domain_remove(struct scmi_device *sdev) +{ + const struct scmi_handle *handle = sdev->handle; + + handle->put_ops(handle, SCMI_PROTOCOL_POWER); +} + static const struct scmi_device_id scmi_id_table[] = { { SCMI_PROTOCOL_POWER, "genpd" }, { }, @@ -120,6 +132,7 @@ MODULE_DEVICE_TABLE(scmi, scmi_id_table); static struct scmi_driver scmi_power_domain_driver = { .name = "scmi-power-domain", .probe = scmi_pm_domain_probe, + .remove = scmi_pm_domain_remove, .id_table = scmi_id_table, }; module_scmi_driver(scmi_power_domain_driver); diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c index 8a0a599558ba..e0129dcd322f 100644 --- a/drivers/firmware/arm_scmi/sensors.c +++ b/drivers/firmware/arm_scmi/sensors.c @@ -334,7 +334,7 @@ static const struct scmi_event_ops sensor_event_ops = { .fill_custom_report = scmi_sensor_fill_custom_report, }; -static int scmi_sensors_protocol_init(struct scmi_handle *handle) +static int scmi_sensors_protocol_init(const struct scmi_handle *handle) { u32 version; struct sensors_info *sinfo; @@ -364,7 +364,6 @@ static int scmi_sensors_protocol_init(struct scmi_handle *handle) sinfo->num_sensors); sinfo->version = version; - handle->sensor_ops = &sensor_ops; return scmi_set_proto_priv(handle, SCMI_PROTOCOL_SENSOR, sinfo); } diff --git a/drivers/firmware/arm_scmi/system.c b/drivers/firmware/arm_scmi/system.c index 8f53f93c63ca..30e3510c1f07 100644 --- a/drivers/firmware/arm_scmi/system.c +++ b/drivers/firmware/arm_scmi/system.c @@ -101,7 +101,7 @@ static const struct scmi_event_ops system_event_ops = { .fill_custom_report = scmi_system_fill_custom_report, }; -static int scmi_system_protocol_init(struct scmi_handle *handle) +static int scmi_system_protocol_init(const struct scmi_handle *handle) { u32 version; struct scmi_system_info *pinfo; diff --git a/drivers/hwmon/scmi-hwmon.c b/drivers/hwmon/scmi-hwmon.c index d421e691318b..27ef71996a15 100644 --- a/drivers/hwmon/scmi-hwmon.c +++ b/drivers/hwmon/scmi-hwmon.c @@ -2,7 +2,7 @@ /* * System Control and Management Interface(SCMI) based hwmon sensor driver * - * Copyright (C) 2018 ARM Ltd. + * Copyright (C) 2018-2020 ARM Ltd. * Sudeep Holla */ @@ -13,6 +13,8 @@ #include #include +static const struct scmi_sensor_ops *sensor_ops; + struct scmi_sensors { const struct scmi_handle *handle; const struct scmi_sensor_info **info[hwmon_max]; @@ -72,7 +74,7 @@ static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, const struct scmi_handle *h = scmi_sensors->handle; sensor = *(scmi_sensors->info[type] + channel); - ret = h->sensor_ops->reading_get(h, sensor->id, &value); + ret = sensor_ops->reading_get(h, sensor->id, &value); if (ret) return ret; @@ -170,10 +172,14 @@ static int scmi_hwmon_probe(struct scmi_device *sdev) const struct hwmon_channel_info **ptr_scmi_ci; const struct scmi_handle *handle = sdev->handle; - if (!handle || !handle->sensor_ops) + if (!handle) return -ENODEV; - nr_sensors = handle->sensor_ops->count_get(handle); + sensor_ops = handle->get_ops(handle, SCMI_PROTOCOL_SENSOR); + if (IS_ERR(sensor_ops)) + return PTR_ERR(sensor_ops); + + nr_sensors = sensor_ops->count_get(handle); if (!nr_sensors) return -EIO; @@ -184,7 +190,7 @@ static int scmi_hwmon_probe(struct scmi_device *sdev) scmi_sensors->handle = handle; for (i = 0; i < nr_sensors; i++) { - sensor = handle->sensor_ops->info_get(handle, i); + sensor = sensor_ops->info_get(handle, i); if (!sensor) return -EINVAL; @@ -234,7 +240,7 @@ static int scmi_hwmon_probe(struct scmi_device *sdev) } for (i = nr_sensors - 1; i >= 0 ; i--) { - sensor = handle->sensor_ops->info_get(handle, i); + sensor = sensor_ops->info_get(handle, i); if (!sensor) continue; @@ -258,6 +264,13 @@ static int scmi_hwmon_probe(struct scmi_device *sdev) return PTR_ERR_OR_ZERO(hwdev); } +static void scmi_hwmon_remove(struct scmi_device *sdev) +{ + const struct scmi_handle *handle = sdev->handle; + + handle->put_ops(handle, SCMI_PROTOCOL_SENSOR); +} + static const struct scmi_device_id scmi_id_table[] = { { SCMI_PROTOCOL_SENSOR, "hwmon" }, { }, @@ -267,6 +280,7 @@ MODULE_DEVICE_TABLE(scmi, scmi_id_table); static struct scmi_driver scmi_hwmon_drv = { .name = "scmi-hwmon", .probe = scmi_hwmon_probe, + .remove = scmi_hwmon_remove, .id_table = scmi_id_table, }; module_scmi_driver(scmi_hwmon_drv); diff --git a/drivers/reset/reset-scmi.c b/drivers/reset/reset-scmi.c index 8d3a858e3b19..e48220dedb35 100644 --- a/drivers/reset/reset-scmi.c +++ b/drivers/reset/reset-scmi.c @@ -2,7 +2,7 @@ /* * ARM System Control and Management Interface (ARM SCMI) reset driver * - * Copyright (C) 2019 ARM Ltd. + * Copyright (C) 2019-2020 ARM Ltd. */ #include @@ -11,6 +11,8 @@ #include #include +static const struct scmi_reset_ops *reset_ops; + /** * struct scmi_reset_data - reset controller information structure * @rcdev: reset controller entity @@ -39,7 +41,7 @@ scmi_reset_assert(struct reset_controller_dev *rcdev, unsigned long id) { const struct scmi_handle *handle = to_scmi_handle(rcdev); - return handle->reset_ops->assert(handle, id); + return reset_ops->assert(handle, id); } /** @@ -57,7 +59,7 @@ scmi_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) { const struct scmi_handle *handle = to_scmi_handle(rcdev); - return handle->reset_ops->deassert(handle, id); + return reset_ops->deassert(handle, id); } /** @@ -75,7 +77,7 @@ scmi_reset_reset(struct reset_controller_dev *rcdev, unsigned long id) { const struct scmi_handle *handle = to_scmi_handle(rcdev); - return handle->reset_ops->reset(handle, id); + return reset_ops->reset(handle, id); } static const struct reset_control_ops scmi_reset_ops = { @@ -91,9 +93,13 @@ static int scmi_reset_probe(struct scmi_device *sdev) struct device_node *np = dev->of_node; const struct scmi_handle *handle = sdev->handle; - if (!handle || !handle->reset_ops) + if (!handle) return -ENODEV; + reset_ops = handle->get_ops(handle, SCMI_PROTOCOL_RESET); + if (IS_ERR(reset_ops)) + return PTR_ERR(reset_ops); + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -101,12 +107,19 @@ static int scmi_reset_probe(struct scmi_device *sdev) data->rcdev.ops = &scmi_reset_ops; data->rcdev.owner = THIS_MODULE; data->rcdev.of_node = np; - data->rcdev.nr_resets = handle->reset_ops->num_domains_get(handle); + data->rcdev.nr_resets = reset_ops->num_domains_get(handle); data->handle = handle; return devm_reset_controller_register(dev, &data->rcdev); } +static void scmi_reset_remove(struct scmi_device *sdev) +{ + const struct scmi_handle *handle = sdev->handle; + + handle->put_ops(handle, SCMI_PROTOCOL_RESET); +} + static const struct scmi_device_id scmi_id_table[] = { { SCMI_PROTOCOL_RESET, "reset" }, { }, @@ -116,6 +129,7 @@ MODULE_DEVICE_TABLE(scmi, scmi_id_table); static struct scmi_driver scmi_reset_driver = { .name = "scmi-reset", .probe = scmi_reset_probe, + .remove = scmi_reset_remove, .id_table = scmi_id_table, }; module_scmi_driver(scmi_reset_driver); diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index bc4f06d46bfb..bfe7017cff19 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -257,11 +257,6 @@ struct scmi_notify_ops { * * @dev: pointer to the SCMI device * @version: pointer to the structure containing SCMI version information - * @power_ops: pointer to set of power protocol operations - * @perf_ops: pointer to set of performance protocol operations - * @clk_ops: pointer to set of clock protocol operations - * @sensor_ops: pointer to set of sensor protocol operations - * @reset_ops: pointer to set of reset protocol operations * @notify_ops: pointer to set of notifications related operations * @notify_priv: pointer to private data structure specific to notifications * (for internal use only) @@ -269,11 +264,11 @@ struct scmi_notify_ops { struct scmi_handle { struct device *dev; struct scmi_revision_info *version; - const struct scmi_perf_ops *perf_ops; - const struct scmi_clk_ops *clk_ops; - const struct scmi_power_ops *power_ops; - const struct scmi_sensor_ops *sensor_ops; - const struct scmi_reset_ops *reset_ops; + + const void __must_check *(*get_ops)(const struct scmi_handle *handle, + u8 proto); + void (*put_ops)(const struct scmi_handle *handle, u8 proto); + const struct scmi_notify_ops *notify_ops; void *notify_priv; }; From patchwork Wed Oct 14 15:05:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11837837 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 5E78D921 for ; Wed, 14 Oct 2020 15:07:41 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (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 1255521582 for ; Wed, 14 Oct 2020 15:07:41 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="gwpaHBOR" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1255521582 Authentication-Results: mail.kernel.org; dmarc=fail (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=merlin.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=sNjDD0WbGAGZ1WT7xCSkEhIiF8dQClTZ3OdByuw0KRg=; b=gwpaHBOR/z3J1kCY48L7UtiNqB OIotmCAqwLD+NaCgq6tKQeozpRtT5OYEOjnHhulNHNkoq1n+/KynBFP1pumBAE0c5EZYeUE/MR9Pv 0vDQW3Ntzh10RXbHgbGxCWu4u6B745wz/wLBQ9p+63zaEnOCxwULQjhMpwwuUUbI+3NvBd7wDBHDY C5BSAz120385Zd7gdbHLVeAr84pXXNAtRGbKKhU6UuTxXy6nL35iIIZCxEuyV8WO4ikYPp8G3I3eV kLOh3XJdXtSVflyt2GV2t+87oyhnYHqDTROEDbt+5srBmuth/sC9hB8mtUHqMt/dv5qLLERlpmvyJ Y6l+e3GQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kSiNC-0001Sy-0t; Wed, 14 Oct 2020 15:07:26 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kSiMn-0001Jc-FZ for linux-arm-kernel@lists.infradead.org; Wed, 14 Oct 2020 15:07:03 +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 EC5C3143B; Wed, 14 Oct 2020 08:07:00 -0700 (PDT) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 551C53F71F; Wed, 14 Oct 2020 08:06:59 -0700 (PDT) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH 04/11] firmware: arm_scmi: refactor events registration Date: Wed, 14 Oct 2020 16:05:38 +0100 Message-Id: <20201014150545.44807-5-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201014150545.44807-1-cristian.marussi@arm.com> References: <20201014150545.44807-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201014_110701_834803_F441423C X-CRM114-Status: GOOD ( 26.93 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.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: f.fainelli@gmail.com, vincent.guittot@linaro.org, sudeep.holla@arm.com, thara.gopinath@linaro.org, cristian.marussi@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, souvik.chakravarty@arm.com, etienne.carriere@linaro.org, lukasz.luba@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 Describe statically the protocol events as part of struct scmi_protocol and move the explicit registraton/deregistration code out the per-protocol specific code and into the common core initialization code. Add .get_num_sources to scmi_event_ops, to resolve at run-time the number of available sources where not statically definable in .num-sources. Simplify scmi_register_protocol_events devres handling since the events resources can now be handled by the per-protocol devres. Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/base.c | 15 +++--- drivers/firmware/arm_scmi/common.h | 4 ++ drivers/firmware/arm_scmi/driver.c | 7 +++ drivers/firmware/arm_scmi/notify.c | 77 ++++++++++++++++++++--------- drivers/firmware/arm_scmi/notify.h | 30 +++++++++-- drivers/firmware/arm_scmi/perf.c | 26 +++++++--- drivers/firmware/arm_scmi/power.c | 26 +++++++--- drivers/firmware/arm_scmi/reset.c | 26 +++++++--- drivers/firmware/arm_scmi/sensors.c | 26 +++++++--- drivers/firmware/arm_scmi/system.c | 16 +++--- 10 files changed, 187 insertions(+), 66 deletions(-) diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c index 129633e6fff4..f40821eeb103 100644 --- a/drivers/firmware/arm_scmi/base.c +++ b/drivers/firmware/arm_scmi/base.c @@ -318,6 +318,14 @@ static const struct scmi_event_ops base_event_ops = { .fill_custom_report = scmi_base_fill_custom_report, }; +static const struct scmi_protocol_events base_protocol_events = { + .queue_sz = 4 * SCMI_PROTO_QUEUE_SZ, + .ops = &base_event_ops, + .evts = base_events, + .num_events = ARRAY_SIZE(base_events), + .num_sources = SCMI_BASE_NUM_SOURCES, +}; + static int scmi_base_protocol_init(const struct scmi_handle *h) { int id, ret; @@ -352,12 +360,6 @@ static int scmi_base_protocol_init(const 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, SCMI_PROTOCOL_BASE, - (4 * SCMI_PROTO_QUEUE_SZ), - &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); @@ -370,6 +372,7 @@ static struct scmi_protocol scmi_base = { .id = SCMI_PROTOCOL_BASE, .init = &scmi_base_protocol_init, .ops = NULL, + .events = &base_protocol_events, }; DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(base, scmi_base) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 56ebb710ee84..66574f57e304 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -19,6 +19,8 @@ #include +#include "notify.h" + #define SCMI_MAX_PROTO 256 #define PROTOCOL_REV_MINOR_MASK GENMASK(15, 0) @@ -167,12 +169,14 @@ typedef int (*scmi_prot_init_fn_t)(const struct scmi_handle *); * @deinit: Optional protocol de-initialization function. * @ops: Optional reference to the operations provided by the protocol and * exposed in scmi_protocol.h. + * @events: An optional reference to the events supported by this protocol. */ struct scmi_protocol { const u8 id; const scmi_prot_init_fn_t init; const scmi_prot_init_fn_t deinit; const void *ops; + const struct scmi_protocol_events *events; }; int __init scmi_bus_init(void); diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 049220efd227..378749040162 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -628,6 +628,10 @@ scmi_get_protocol_instance(const struct scmi_handle *handle, u8 protocol_id) /* Ensure initialized protocol is visible */ smp_wmb(); + if (pi->proto->events) + scmi_register_protocol_events(handle, pi->proto->id, + pi->proto->events); + devres_close_group(handle->dev, pi->gid); dev_dbg(handle->dev, "Initialized protocol: 0x%X\n", protocol_id); @@ -685,6 +689,9 @@ void scmi_release_protocol(const struct scmi_handle *handle, u8 protocol_id) if (refcount_dec_and_test(&pi->users)) { void *gid = pi->gid; + if (pi->proto->events) + scmi_deregister_protocol_events(handle, protocol_id); + if (pi->proto->deinit) pi->proto->deinit(handle); diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c index 02b00af9b08f..7ba182d4f2b4 100644 --- a/drivers/firmware/arm_scmi/notify.c +++ b/drivers/firmware/arm_scmi/notify.c @@ -731,14 +731,9 @@ scmi_allocate_registered_events_desc(struct scmi_notify_instance *ni, /** * scmi_register_protocol_events() - Register Protocol Events with the core * @handle: The handle identifying the platform instance against which the - * the protocol's events are registered + * protocol's events are registered * @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. + * @ee: A structure describing the events supported by this protocol. * * Used by SCMI Protocols initialization code to register with the notification * core the list of supported events and their descriptors: takes care to @@ -747,18 +742,18 @@ scmi_allocate_registered_events_desc(struct scmi_notify_instance *ni, * * Return: 0 on Success */ -int scmi_register_protocol_events(const struct scmi_handle *handle, - u8 proto_id, size_t queue_sz, - const struct scmi_event_ops *ops, - const struct scmi_event *evt, int num_events, - int num_sources) +int scmi_register_protocol_events(const struct scmi_handle *handle, u8 proto_id, + const struct scmi_protocol_events *ee) { int i; + unsigned int num_sources; size_t payld_sz = 0; struct scmi_registered_events_desc *pd; struct scmi_notify_instance *ni; + const struct scmi_event *evt; - if (!ops || !evt) + if (!ee || !ee->ops || !ee->evts || + (!ee->num_sources && !ee->ops->get_num_sources)) return -EINVAL; /* Ensure notify_priv is updated */ @@ -767,20 +762,29 @@ int scmi_register_protocol_events(const struct scmi_handle *handle, return -ENOMEM; ni = handle->notify_priv; - /* Attach to the notification main devres group */ - if (!devres_open_group(ni->handle->dev, ni->gid, GFP_KERNEL)) - return -ENOMEM; + /* num_sources cannot be <= 0 */ + if (ee->num_sources) { + num_sources = ee->num_sources; + } else { + int nsrc = ee->ops->get_num_sources(handle); + + if (nsrc <= 0) + return -EINVAL; + num_sources = nsrc; + } - for (i = 0; i < num_events; i++) + evt = ee->evts; + for (i = 0; i < ee->num_events; i++) payld_sz = max_t(size_t, payld_sz, evt[i].max_payld_sz); payld_sz += sizeof(struct scmi_event_header); - pd = scmi_allocate_registered_events_desc(ni, proto_id, queue_sz, - payld_sz, num_events, ops); + pd = scmi_allocate_registered_events_desc(ni, proto_id, ee->queue_sz, + payld_sz, ee->num_events, + ee->ops); if (IS_ERR(pd)) goto err; - for (i = 0; i < num_events; i++, evt++) { + for (i = 0; i < ee->num_events; i++, evt++) { struct scmi_registered_event *r_evt; r_evt = devm_kzalloc(ni->handle->dev, sizeof(*r_evt), @@ -814,8 +818,6 @@ int scmi_register_protocol_events(const struct scmi_handle *handle, /* Ensure protocols are updated */ smp_wmb(); - devres_close_group(ni->handle->dev, ni->gid); - /* * Finalize any pending events' handler which could have been waiting * for this protocol's events registration. @@ -826,12 +828,39 @@ int scmi_register_protocol_events(const struct scmi_handle *handle, err: dev_warn(handle->dev, "Proto:%X - Registration Failed !\n", proto_id); - /* A failing protocol registration does not trigger full failure */ - devres_close_group(ni->handle->dev, ni->gid); return -ENOMEM; } +/** + * scmi_deregister_protocol_events - Deregister protocol events with the core + * @handle: The handle identifying the platform instance against which the + * protocol's events are registered + * @proto_id: Protocol ID + */ +void scmi_deregister_protocol_events(const struct scmi_handle *handle, + u8 proto_id) +{ + struct scmi_notify_instance *ni; + struct scmi_registered_events_desc *pd; + + /* Ensure notify_priv is updated */ + smp_rmb(); + if (!handle->notify_priv) + return; + + ni = handle->notify_priv; + pd = ni->registered_protocols[proto_id]; + if (!pd) + return; + + ni->registered_protocols[proto_id] = NULL; + /* Ensure protocols are updated */ + smp_wmb(); + + cancel_work_sync(&pd->equeue.notify_work); +} + /** * scmi_allocate_event_handler() - Allocate Event handler * @ni: A reference to the notification instance to use diff --git a/drivers/firmware/arm_scmi/notify.h b/drivers/firmware/arm_scmi/notify.h index 3485f20fa70e..bc30167b1dd6 100644 --- a/drivers/firmware/arm_scmi/notify.h +++ b/drivers/firmware/arm_scmi/notify.h @@ -33,6 +33,8 @@ struct scmi_event { /** * struct scmi_event_ops - Protocol helpers called by the notification core. + * @get_num_sources: Returns the number of possible events' sources for this + * protocol * @set_notify_enabled: Enable/disable the required evt_id/src_id notifications * using the proper custom protocol commands. * Return 0 on Success @@ -46,6 +48,7 @@ struct scmi_event { * process context. */ struct scmi_event_ops { + int (*get_num_sources)(const struct scmi_handle *handle); int (*set_notify_enabled)(const struct scmi_handle *handle, u8 evt_id, u32 src_id, bool enabled); void *(*fill_custom_report)(const struct scmi_handle *handle, @@ -54,14 +57,31 @@ struct scmi_event_ops { void *report, u32 *src_id); }; +/** + * struct scmi_protocol_events - Per-protocol description of available events + * @queue_sz: Size in bytes of the per-protocol queue to use. + * @ops: Array of protocol-specific events operations. + * @evts: Array of supported protocol's events. + * @num_events: Number of supported protocol's events described in @evts. + * @num_sources: Number of protocol's sources, should be greater than 0; if not + * available at compile time, it will be provided at run-time via + * @get_num_sources. + */ +struct scmi_protocol_events { + size_t queue_sz; + const struct scmi_event_ops *ops; + const struct scmi_event *evts; + unsigned int num_events; + unsigned int num_sources; +}; + int scmi_notification_init(struct scmi_handle *handle); void scmi_notification_exit(struct scmi_handle *handle); -int scmi_register_protocol_events(const struct scmi_handle *handle, - u8 proto_id, size_t queue_sz, - const struct scmi_event_ops *ops, - const struct scmi_event *evt, int num_events, - int num_sources); +int scmi_register_protocol_events(const struct scmi_handle *handle, u8 proto_id, + const struct scmi_protocol_events *ee); +void scmi_deregister_protocol_events(const struct scmi_handle *handle, + u8 proto_id); int scmi_notify(const struct scmi_handle *handle, u8 proto_id, u8 evt_id, const void *buf, size_t len, ktime_t ts); diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c index bd9cb2583557..b3038362f362 100644 --- a/drivers/firmware/arm_scmi/perf.c +++ b/drivers/firmware/arm_scmi/perf.c @@ -839,6 +839,17 @@ static void *scmi_perf_fill_custom_report(const struct scmi_handle *handle, return rep; } +static int scmi_perf_get_num_sources(const struct scmi_handle *handle) +{ + struct scmi_perf_info *pinfo = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_PERF); + + if (!pinfo) + return -EINVAL; + + return pinfo->num_domains; +} + static const struct scmi_event perf_events[] = { { .id = SCMI_EVENT_PERFORMANCE_LIMITS_CHANGED, @@ -853,10 +864,18 @@ static const struct scmi_event perf_events[] = { }; static const struct scmi_event_ops perf_event_ops = { + .get_num_sources = scmi_perf_get_num_sources, .set_notify_enabled = scmi_perf_set_notify_enabled, .fill_custom_report = scmi_perf_fill_custom_report, }; +static const struct scmi_protocol_events perf_protocol_events = { + .queue_sz = SCMI_PROTO_QUEUE_SZ, + .ops = &perf_event_ops, + .evts = perf_events, + .num_events = ARRAY_SIZE(perf_events), +}; + static int scmi_perf_protocol_init(const struct scmi_handle *handle) { int domain; @@ -889,12 +908,6 @@ static int scmi_perf_protocol_init(const struct scmi_handle *handle) scmi_perf_domain_init_fc(handle, domain, &dom->fc_info); } - scmi_register_protocol_events(handle, - SCMI_PROTOCOL_PERF, SCMI_PROTO_QUEUE_SZ, - &perf_event_ops, perf_events, - ARRAY_SIZE(perf_events), - pinfo->num_domains); - pinfo->version = version; return scmi_set_proto_priv(handle, SCMI_PROTOCOL_PERF, pinfo); } @@ -903,6 +916,7 @@ static struct scmi_protocol scmi_perf = { .id = SCMI_PROTOCOL_PERF, .init = &scmi_perf_protocol_init, .ops = &perf_ops, + .events = &perf_protocol_events, }; DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(perf, scmi_perf) diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c index 1e026b5530a7..cb9b1f6a56dd 100644 --- a/drivers/firmware/arm_scmi/power.c +++ b/drivers/firmware/arm_scmi/power.c @@ -248,6 +248,17 @@ static void *scmi_power_fill_custom_report(const struct scmi_handle *handle, return r; } +static int scmi_power_get_num_sources(const struct scmi_handle *handle) +{ + struct scmi_power_info *pinfo = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_POWER); + + if (!pinfo) + return -EINVAL; + + return pinfo->num_domains; +} + static const struct scmi_event power_events[] = { { .id = SCMI_EVENT_POWER_STATE_CHANGED, @@ -258,10 +269,18 @@ static const struct scmi_event power_events[] = { }; static const struct scmi_event_ops power_event_ops = { + .get_num_sources = scmi_power_get_num_sources, .set_notify_enabled = scmi_power_set_notify_enabled, .fill_custom_report = scmi_power_fill_custom_report, }; +static const struct scmi_protocol_events power_protocol_events = { + .queue_sz = SCMI_PROTO_QUEUE_SZ, + .ops = &power_event_ops, + .evts = power_events, + .num_events = ARRAY_SIZE(power_events), +}; + static int scmi_power_protocol_init(const struct scmi_handle *handle) { int domain; @@ -290,12 +309,6 @@ static int scmi_power_protocol_init(const struct scmi_handle *handle) scmi_power_domain_attributes_get(handle, domain, dom); } - scmi_register_protocol_events(handle, - SCMI_PROTOCOL_POWER, SCMI_PROTO_QUEUE_SZ, - &power_event_ops, power_events, - ARRAY_SIZE(power_events), - pinfo->num_domains); - pinfo->version = version; return scmi_set_proto_priv(handle, SCMI_PROTOCOL_POWER, pinfo); } @@ -304,6 +317,7 @@ static struct scmi_protocol scmi_power = { .id = SCMI_PROTOCOL_POWER, .init = &scmi_power_protocol_init, .ops = &power_ops, + .events = &power_protocol_events, }; DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(power, scmi_power) diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c index b7da4de0e56e..83bfd0514d4d 100644 --- a/drivers/firmware/arm_scmi/reset.c +++ b/drivers/firmware/arm_scmi/reset.c @@ -261,6 +261,17 @@ static void *scmi_reset_fill_custom_report(const struct scmi_handle *handle, return r; } +static int scmi_reset_get_num_sources(const struct scmi_handle *handle) +{ + struct scmi_reset_info *pinfo = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_RESET); + + if (!pinfo) + return -EINVAL; + + return pinfo->num_domains; +} + static const struct scmi_event reset_events[] = { { .id = SCMI_EVENT_RESET_ISSUED, @@ -270,10 +281,18 @@ static const struct scmi_event reset_events[] = { }; static const struct scmi_event_ops reset_event_ops = { + .get_num_sources = scmi_reset_get_num_sources, .set_notify_enabled = scmi_reset_set_notify_enabled, .fill_custom_report = scmi_reset_fill_custom_report, }; +static const struct scmi_protocol_events reset_protocol_events = { + .queue_sz = SCMI_PROTO_QUEUE_SZ, + .ops = &reset_event_ops, + .evts = reset_events, + .num_events = ARRAY_SIZE(reset_events), +}; + static int scmi_reset_protocol_init(const struct scmi_handle *handle) { int domain; @@ -302,12 +321,6 @@ static int scmi_reset_protocol_init(const struct scmi_handle *handle) scmi_reset_domain_attributes_get(handle, domain, dom); } - scmi_register_protocol_events(handle, - SCMI_PROTOCOL_RESET, SCMI_PROTO_QUEUE_SZ, - &reset_event_ops, reset_events, - ARRAY_SIZE(reset_events), - pinfo->num_domains); - pinfo->version = version; return scmi_set_proto_priv(handle, SCMI_PROTOCOL_RESET, pinfo); } @@ -316,6 +329,7 @@ static struct scmi_protocol scmi_reset = { .id = SCMI_PROTOCOL_RESET, .init = &scmi_reset_protocol_init, .ops = &reset_ops, + .events = &reset_protocol_events, }; DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(reset, scmi_reset) diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c index e0129dcd322f..79bdd53ab7ba 100644 --- a/drivers/firmware/arm_scmi/sensors.c +++ b/drivers/firmware/arm_scmi/sensors.c @@ -321,6 +321,17 @@ static void *scmi_sensor_fill_custom_report(const struct scmi_handle *handle, return r; } +static int scmi_sensor_get_num_sources(const struct scmi_handle *handle) +{ + struct sensors_info *sinfo = + scmi_get_proto_priv(handle, SCMI_PROTOCOL_SENSOR); + + if (!sinfo) + return -EINVAL; + + return sinfo->num_sensors; +} + static const struct scmi_event sensor_events[] = { { .id = SCMI_EVENT_SENSOR_TRIP_POINT_EVENT, @@ -330,10 +341,18 @@ static const struct scmi_event sensor_events[] = { }; static const struct scmi_event_ops sensor_event_ops = { + .get_num_sources = scmi_sensor_get_num_sources, .set_notify_enabled = scmi_sensor_set_notify_enabled, .fill_custom_report = scmi_sensor_fill_custom_report, }; +static const struct scmi_protocol_events sensor_protocol_events = { + .queue_sz = SCMI_PROTO_QUEUE_SZ, + .ops = &sensor_event_ops, + .evts = sensor_events, + .num_events = ARRAY_SIZE(sensor_events), +}; + static int scmi_sensors_protocol_init(const struct scmi_handle *handle) { u32 version; @@ -357,12 +376,6 @@ static int scmi_sensors_protocol_init(const struct scmi_handle *handle) scmi_sensor_description_get(handle, sinfo); - scmi_register_protocol_events(handle, - SCMI_PROTOCOL_SENSOR, SCMI_PROTO_QUEUE_SZ, - &sensor_event_ops, sensor_events, - ARRAY_SIZE(sensor_events), - sinfo->num_sensors); - sinfo->version = version; return scmi_set_proto_priv(handle, SCMI_PROTOCOL_SENSOR, sinfo); } @@ -371,6 +384,7 @@ static struct scmi_protocol scmi_sensors = { .id = SCMI_PROTOCOL_SENSOR, .init = &scmi_sensors_protocol_init, .ops = &sensor_ops, + .events = &sensor_protocol_events, }; DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(sensors, scmi_sensors) diff --git a/drivers/firmware/arm_scmi/system.c b/drivers/firmware/arm_scmi/system.c index 30e3510c1f07..ae884fc669f5 100644 --- a/drivers/firmware/arm_scmi/system.c +++ b/drivers/firmware/arm_scmi/system.c @@ -101,6 +101,14 @@ static const struct scmi_event_ops system_event_ops = { .fill_custom_report = scmi_system_fill_custom_report, }; +static const struct scmi_protocol_events system_protocol_events = { + .queue_sz = SCMI_PROTO_QUEUE_SZ, + .ops = &system_event_ops, + .evts = system_events, + .num_events = ARRAY_SIZE(system_events), + .num_sources = SCMI_SYSTEM_NUM_SOURCES, +}; + static int scmi_system_protocol_init(const struct scmi_handle *handle) { u32 version; @@ -115,13 +123,6 @@ static int scmi_system_protocol_init(const struct scmi_handle *handle) if (!pinfo) return -ENOMEM; - scmi_register_protocol_events(handle, - SCMI_PROTOCOL_SYSTEM, SCMI_PROTO_QUEUE_SZ, - &system_event_ops, - system_events, - ARRAY_SIZE(system_events), - SCMI_SYSTEM_NUM_SOURCES); - pinfo->version = version; return scmi_set_proto_priv(handle, SCMI_PROTOCOL_SYSTEM, pinfo); } @@ -130,6 +131,7 @@ static struct scmi_protocol scmi_system = { .id = SCMI_PROTOCOL_SYSTEM, .init = &scmi_system_protocol_init, .ops = NULL, + .events = &system_protocol_events, }; DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(system, scmi_system) From patchwork Wed Oct 14 15:05:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11837851 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 CCF911744 for ; Wed, 14 Oct 2020 15:09:23 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (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 85A2821582 for ; Wed, 14 Oct 2020 15:09:23 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="C+9FqZz/" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 85A2821582 Authentication-Results: mail.kernel.org; dmarc=fail (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=merlin.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=nN+Q7tdfkXweTRFDM868YZppjTlA2Ni1BpgY0cW3+0M=; b=C+9FqZz/Zi5byFxZyQHrQ55jRG 9DAtAf6l5favsZYv7stxX/yel7/X4/Mpj8yRKM1Y5y2xxQQQsnR+CELWbiOnYUyWtgVZDOVu6tJOo YWFmHxcFKKCqQxtRe78IZaDjYFPMhRy7xKtAISZaxwCenMnUtCvJiZhaT3+YPDb+JDdsv/TgjHZIV h/MrhXt1ZS7dQ84qU19RKDdOovrO3uuESFK6dXcThNa94W7G45LF7hPenblDRPK6SHRbQzTeqv+oS cjQs3wNT7V40+UgT941yVPwmFNnGJgvzJHY+Alcg1+AVQprfKj/eKGYWokP5iaXk9Cn5SX99G1Jzj PiQ0BfWA==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kSiNH-0001UJ-Ep; Wed, 14 Oct 2020 15:07:31 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kSiMp-0001KD-5H for linux-arm-kernel@lists.infradead.org; Wed, 14 Oct 2020 15:07:04 +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 C81CE143D; Wed, 14 Oct 2020 08:07:02 -0700 (PDT) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 2F5883F71F; Wed, 14 Oct 2020 08:07:01 -0700 (PDT) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH 05/11] firmware: arm_scmi: make notify_priv really private Date: Wed, 14 Oct 2020 16:05:39 +0100 Message-Id: <20201014150545.44807-6-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201014150545.44807-1-cristian.marussi@arm.com> References: <20201014150545.44807-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201014_110703_313491_9FDBDF5D X-CRM114-Status: GOOD ( 17.42 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.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: f.fainelli@gmail.com, vincent.guittot@linaro.org, sudeep.holla@arm.com, thara.gopinath@linaro.org, cristian.marussi@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, souvik.chakravarty@arm.com, etienne.carriere@linaro.org, lukasz.luba@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 Notification private data is currently accessible via handle->notify_priv; this data was indeed meant to be private to the notification core support and not to be accessible to SCMI drivers: make it private hiding it inside instance descriptor struct scmi_info. Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/common.h | 4 +++ drivers/firmware/arm_scmi/driver.c | 21 +++++++++++++ drivers/firmware/arm_scmi/notify.c | 49 +++++++++++------------------- include/linux/scmi_protocol.h | 3 -- 4 files changed, 43 insertions(+), 34 deletions(-) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 66574f57e304..5a91e3324697 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -295,4 +295,8 @@ void shmem_clear_channel(struct scmi_shared_mem __iomem *shmem); bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem, struct scmi_xfer *xfer); +void scmi_set_notification_instance_data(const struct scmi_handle *handle, + void *priv); +void *scmi_get_notification_instance_data(const struct scmi_handle *handle); + #endif /* _SCMI_COMMON_H */ diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 378749040162..25a4152537e6 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -106,6 +106,7 @@ struct scmi_protocol_instance { * they have to sit on their own. * @protocols_imp: List of protocols implemented, currently maximum of * MAX_PROTOCOLS_IMP elements allocated by the base protocol + * @notify_priv: Pointer to private data structure specific to notifications. * @node: List head * @users: Number of users of this instance */ @@ -123,6 +124,7 @@ struct scmi_info { struct mutex protocols_mtx; void *protocols_private_data[SCMI_MAX_PROTO]; u8 *protocols_imp; + void *notify_priv; struct list_head node; int users; }; @@ -164,6 +166,25 @@ static inline void scmi_dump_header_dbg(struct device *dev, hdr->id, hdr->seq, hdr->protocol_id); } +void scmi_set_notification_instance_data(const struct scmi_handle *handle, + void *priv) +{ + struct scmi_info *info = handle_to_scmi_info(handle); + + info->notify_priv = priv; + /* Ensure updated protocol private date are visible */ + smp_wmb(); +} + +void *scmi_get_notification_instance_data(const struct scmi_handle *handle) +{ + struct scmi_info *info = handle_to_scmi_info(handle); + + /* Ensure protocols_private_data has been updated */ + smp_rmb(); + return info->notify_priv; +} + /** * scmi_xfer_get() - Allocate one message * diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c index 7ba182d4f2b4..d89d9c08e660 100644 --- a/drivers/firmware/arm_scmi/notify.c +++ b/drivers/firmware/arm_scmi/notify.c @@ -578,11 +578,9 @@ int scmi_notify(const struct scmi_handle *handle, u8 proto_id, u8 evt_id, struct scmi_event_header eh; struct scmi_notify_instance *ni; - /* Ensure notify_priv is updated */ - smp_rmb(); - if (!handle->notify_priv) + ni = scmi_get_notification_instance_data(handle); + if (!ni) return 0; - ni = handle->notify_priv; r_evt = SCMI_GET_REVT(ni, proto_id, evt_id); if (!r_evt) @@ -756,11 +754,9 @@ int scmi_register_protocol_events(const struct scmi_handle *handle, u8 proto_id, (!ee->num_sources && !ee->ops->get_num_sources)) return -EINVAL; - /* Ensure notify_priv is updated */ - smp_rmb(); - if (!handle->notify_priv) + ni = scmi_get_notification_instance_data(handle); + if (!ni) return -ENOMEM; - ni = handle->notify_priv; /* num_sources cannot be <= 0 */ if (ee->num_sources) { @@ -844,12 +840,10 @@ void scmi_deregister_protocol_events(const struct scmi_handle *handle, struct scmi_notify_instance *ni; struct scmi_registered_events_desc *pd; - /* Ensure notify_priv is updated */ - smp_rmb(); - if (!handle->notify_priv) + ni = scmi_get_notification_instance_data(handle); + if (!ni) return; - ni = handle->notify_priv; pd = ni->registered_protocols[proto_id]; if (!pd) return; @@ -1352,11 +1346,9 @@ static int scmi_register_notifier(const struct scmi_handle *handle, struct scmi_event_handler *hndl; struct scmi_notify_instance *ni; - /* Ensure notify_priv is updated */ - smp_rmb(); - if (!handle->notify_priv) + ni = scmi_get_notification_instance_data(handle); + if (!ni) return -ENODEV; - ni = handle->notify_priv; evt_key = MAKE_HASH_KEY(proto_id, evt_id, src_id ? *src_id : SRC_ID_MASK); @@ -1400,11 +1392,9 @@ static int scmi_unregister_notifier(const struct scmi_handle *handle, struct scmi_event_handler *hndl; struct scmi_notify_instance *ni; - /* Ensure notify_priv is updated */ - smp_rmb(); - if (!handle->notify_priv) + ni = scmi_get_notification_instance_data(handle); + if (!ni) return -ENODEV; - ni = handle->notify_priv; evt_key = MAKE_HASH_KEY(proto_id, evt_id, src_id ? *src_id : SRC_ID_MASK); @@ -1554,8 +1544,8 @@ int scmi_notification_init(struct scmi_handle *handle) INIT_WORK(&ni->init_work, scmi_protocols_late_init); + scmi_set_notification_instance_data(handle, ni); handle->notify_ops = ¬ify_ops; - handle->notify_priv = ni; /* Ensure handle is up to date */ smp_wmb(); @@ -1567,7 +1557,7 @@ int scmi_notification_init(struct scmi_handle *handle) err: dev_warn(handle->dev, "Initialization Failed.\n"); - devres_release_group(handle->dev, NULL); + devres_release_group(handle->dev, gid); return -ENOMEM; } @@ -1578,19 +1568,16 @@ int scmi_notification_init(struct scmi_handle *handle) void scmi_notification_exit(struct scmi_handle *handle) { struct scmi_notify_instance *ni; + void *gid; - /* Ensure notify_priv is updated */ - smp_rmb(); - if (!handle->notify_priv) + ni = scmi_get_notification_instance_data(handle); + if (!ni) return; - ni = handle->notify_priv; - - handle->notify_priv = NULL; - /* Ensure handle is up to date */ - smp_wmb(); + scmi_set_notification_instance_data(handle, NULL); /* Destroy while letting pending work complete */ destroy_workqueue(ni->notify_wq); - devres_release_group(ni->handle->dev, ni->gid); + gid = ni->gid; + devres_release_group(ni->handle->dev, gid); } diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index bfe7017cff19..650d0877a5c8 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -258,8 +258,6 @@ struct scmi_notify_ops { * @dev: pointer to the SCMI device * @version: pointer to the structure containing SCMI version information * @notify_ops: pointer to set of notifications related operations - * @notify_priv: pointer to private data structure specific to notifications - * (for internal use only) */ struct scmi_handle { struct device *dev; @@ -270,7 +268,6 @@ struct scmi_handle { void (*put_ops)(const struct scmi_handle *handle, u8 proto); const struct scmi_notify_ops *notify_ops; - void *notify_priv; }; enum scmi_std_protocol { From patchwork Wed Oct 14 15:05:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11837857 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 2744E1580 for ; Wed, 14 Oct 2020 15:10:16 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (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 B744421582 for ; Wed, 14 Oct 2020 15:10:15 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="Hp61PibU" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B744421582 Authentication-Results: mail.kernel.org; dmarc=fail (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=merlin.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=FL4HFbKWX9cphXV4OtjWdRYAeUCEcSFtlsj4CU6Zw3A=; b=Hp61PibUvyuu4Ipc9ufNqBO+pI H1MMDoOxjWHREpkL6/gW5Yi8v+w8vFXPVXi81noZhD3aROcMLd1uFClB2qF6ZxjB8Ua4UHJYpBPyN AV0WZUO7LNsQ87j5bgmSkK/QRjA0HQIaosAzCx2/Qd/4ejRxj41xfSHMXeK1KlvFwQvVLAisqisOv HbgN5F2gTGCLO7yDRB7BPEdd8rx+WtwyxEIYSLIftewey+DuTlEraE4EyTaBlPKgFcZqAsLIWUMBh uDYRHSeRse65h2M3vmHxdBh5oPvxPuKM0VLMKURHUlNE/YmR6dFxXZEsS4NjiXTbrbNNMfCRVSsy3 8WPrZ+Mw==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kSiNx-0001ku-Gw; Wed, 14 Oct 2020 15:08:13 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kSiMr-0001L0-4V for linux-arm-kernel@lists.infradead.org; Wed, 14 Oct 2020 15:07:17 +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 A6CE11474; Wed, 14 Oct 2020 08:07:04 -0700 (PDT) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 0B89C3F71F; Wed, 14 Oct 2020 08:07:02 -0700 (PDT) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH 06/11] firmware: arm_scmi: add support for protocol modularization Date: Wed, 14 Oct 2020 16:05:40 +0100 Message-Id: <20201014150545.44807-7-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201014150545.44807-1-cristian.marussi@arm.com> References: <20201014150545.44807-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201014_110705_429266_36D55D37 X-CRM114-Status: GOOD ( 18.56 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.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: f.fainelli@gmail.com, vincent.guittot@linaro.org, sudeep.holla@arm.com, thara.gopinath@linaro.org, cristian.marussi@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, souvik.chakravarty@arm.com, etienne.carriere@linaro.org, lukasz.luba@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 Modify protocol initialization callback adding a new parameter representing a reference to the available xfer core operations and introduce a macro to simply register with the core new protocols as loadable drivers. Keep standard protocols as builtin. Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/base.c | 56 ++++++++++-------- drivers/firmware/arm_scmi/bus.c | 14 ++++- drivers/firmware/arm_scmi/clock.c | 56 +++++++++--------- drivers/firmware/arm_scmi/common.h | 42 +++++++++----- drivers/firmware/arm_scmi/driver.c | 50 ++++++++++------ drivers/firmware/arm_scmi/perf.c | 88 +++++++++++++++-------------- drivers/firmware/arm_scmi/power.c | 46 ++++++++------- drivers/firmware/arm_scmi/reset.c | 46 ++++++++------- drivers/firmware/arm_scmi/sensors.c | 52 +++++++++-------- drivers/firmware/arm_scmi/system.c | 16 ++++-- include/linux/scmi_protocol.h | 18 +++++- 11 files changed, 288 insertions(+), 196 deletions(-) diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c index f40821eeb103..8d7214fd2187 100644 --- a/drivers/firmware/arm_scmi/base.c +++ b/drivers/firmware/arm_scmi/base.c @@ -15,6 +15,8 @@ #define SCMI_BASE_NUM_SOURCES 1 #define SCMI_BASE_MAX_CMD_ERR_COUNT 1024 +static const struct scmi_xfer_ops *ops; + enum scmi_base_protocol_cmd { BASE_DISCOVER_VENDOR = 0x3, BASE_DISCOVER_SUB_VENDOR = 0x4, @@ -61,19 +63,19 @@ static int scmi_base_attributes_get(const struct scmi_handle *handle) struct scmi_msg_resp_base_attributes *attr_info; struct scmi_revision_info *rev = handle->version; - ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES, + ret = ops->xfer_get_init(handle, PROTOCOL_ATTRIBUTES, SCMI_PROTOCOL_BASE, 0, sizeof(*attr_info), &t); if (ret) return ret; - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (!ret) { attr_info = t->rx.buf; rev->num_protocols = attr_info->num_protocols; rev->num_agents = attr_info->num_agents; } - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -105,15 +107,15 @@ scmi_base_vendor_id_get(const struct scmi_handle *handle, bool sub_vendor) size = ARRAY_SIZE(rev->vendor_id); } - ret = scmi_xfer_get_init(handle, cmd, SCMI_PROTOCOL_BASE, 0, size, &t); + ret = ops->xfer_get_init(handle, cmd, SCMI_PROTOCOL_BASE, 0, size, &t); if (ret) return ret; - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (!ret) memcpy(vendor_id, t->rx.buf, size); - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -135,18 +137,18 @@ scmi_base_implementation_version_get(const struct scmi_handle *handle) struct scmi_xfer *t; struct scmi_revision_info *rev = handle->version; - ret = scmi_xfer_get_init(handle, BASE_DISCOVER_IMPLEMENT_VERSION, + ret = ops->xfer_get_init(handle, BASE_DISCOVER_IMPLEMENT_VERSION, SCMI_PROTOCOL_BASE, 0, sizeof(*impl_ver), &t); if (ret) return ret; - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (!ret) { impl_ver = t->rx.buf; rev->impl_ver = le32_to_cpu(*impl_ver); } - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -170,7 +172,7 @@ static int scmi_base_implementation_list_get(const struct scmi_handle *handle, u32 tot_num_ret = 0, loop_num_ret; struct device *dev = handle->dev; - ret = scmi_xfer_get_init(handle, BASE_DISCOVER_LIST_PROTOCOLS, + ret = ops->xfer_get_init(handle, BASE_DISCOVER_LIST_PROTOCOLS, SCMI_PROTOCOL_BASE, sizeof(*num_skip), 0, &t); if (ret) return ret; @@ -183,7 +185,7 @@ static int scmi_base_implementation_list_get(const struct scmi_handle *handle, /* Set the number of protocols to be skipped/already read */ *num_skip = cpu_to_le32(tot_num_ret); - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (ret) break; @@ -198,10 +200,10 @@ static int scmi_base_implementation_list_get(const struct scmi_handle *handle, tot_num_ret += loop_num_ret; - scmi_reset_rx_to_maxsz(handle, t); + ops->reset_rx_to_maxsz(handle, t); } while (loop_num_ret); - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -224,7 +226,7 @@ static int scmi_base_discover_agent_get(const struct scmi_handle *handle, int ret; struct scmi_xfer *t; - ret = scmi_xfer_get_init(handle, BASE_DISCOVER_AGENT, + ret = ops->xfer_get_init(handle, BASE_DISCOVER_AGENT, SCMI_PROTOCOL_BASE, sizeof(__le32), SCMI_MAX_STR_SIZE, &t); if (ret) @@ -232,11 +234,11 @@ static int scmi_base_discover_agent_get(const struct scmi_handle *handle, put_unaligned_le32(id, t->tx.buf); - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (!ret) strlcpy(name, t->rx.buf, SCMI_MAX_STR_SIZE); - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -248,7 +250,7 @@ static int scmi_base_error_notify(const struct scmi_handle *handle, bool enable) struct scmi_xfer *t; struct scmi_msg_base_error_notify *cfg; - ret = scmi_xfer_get_init(handle, BASE_NOTIFY_ERRORS, + ret = ops->xfer_get_init(handle, BASE_NOTIFY_ERRORS, SCMI_PROTOCOL_BASE, sizeof(*cfg), 0, &t); if (ret) return ret; @@ -256,9 +258,9 @@ static int scmi_base_error_notify(const struct scmi_handle *handle, bool enable) cfg = t->tx.buf; cfg->event_control = cpu_to_le32(evt_cntl); - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -326,7 +328,8 @@ static const struct scmi_protocol_events base_protocol_events = { .num_sources = SCMI_BASE_NUM_SOURCES, }; -static int scmi_base_protocol_init(const struct scmi_handle *h) +static int scmi_base_protocol_init(const struct scmi_handle *h, + const struct scmi_xfer_ops *xops) { int id, ret; u8 *prot_imp; @@ -336,7 +339,8 @@ static int scmi_base_protocol_init(const struct scmi_handle *h) struct device *dev = handle->dev; struct scmi_revision_info *rev = handle->version; - ret = scmi_version_get(handle, SCMI_PROTOCOL_BASE, &version); + ops = xops; + ret = ops->version_get(handle, SCMI_PROTOCOL_BASE, &version); if (ret) return ret; @@ -375,4 +379,12 @@ static struct scmi_protocol scmi_base = { .events = &base_protocol_events, }; -DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(base, scmi_base) +int __init scmi_base_register(void) +{ + return scmi_protocol_register(&scmi_base, NULL); +} + +void __exit scmi_base_unregister(void) +{ + return scmi_protocol_unregister(&scmi_base); +} diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c index 3a2be1193c85..2ce98fae56e3 100644 --- a/drivers/firmware/arm_scmi/bus.c +++ b/drivers/firmware/arm_scmi/bus.c @@ -56,7 +56,7 @@ const struct scmi_protocol *scmi_get_protocol(int protocol_id) const struct scmi_protocol *proto; proto = idr_find(&scmi_available_protocols, protocol_id); - if (!proto) { + if (!proto || !try_module_get(proto->owner)) { pr_warn("SCMI Protocol 0x%x not found!\n", protocol_id); return NULL; } @@ -66,6 +66,15 @@ const struct scmi_protocol *scmi_get_protocol(int protocol_id) return proto; } +void scmi_put_protocol(int protocol_id) +{ + const struct scmi_protocol *proto; + + proto = idr_find(&scmi_available_protocols, protocol_id); + if (proto) + module_put(proto->owner); +} + static int scmi_dev_probe(struct device *dev) { struct scmi_driver *scmi_drv = to_scmi_driver(dev->driver); @@ -186,7 +195,7 @@ void scmi_set_handle(struct scmi_device *scmi_dev) scmi_dev->handle = scmi_handle_get(&scmi_dev->dev); } -int scmi_protocol_register(struct scmi_protocol *proto) +int scmi_protocol_register(struct scmi_protocol *proto, struct module *owner) { int ret; @@ -200,6 +209,7 @@ int scmi_protocol_register(struct scmi_protocol *proto) return -EINVAL; } + proto->owner = owner; spin_lock(&protocol_lock); ret = idr_alloc(&scmi_available_protocols, proto, proto->id, proto->id + 1, GFP_ATOMIC); diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c index 539c94860b8f..a2f552c87b3e 100644 --- a/drivers/firmware/arm_scmi/clock.c +++ b/drivers/firmware/arm_scmi/clock.c @@ -9,6 +9,8 @@ #include "common.h" +static const struct scmi_xfer_ops *ops; + enum scmi_clock_protocol_cmd { CLOCK_ATTRIBUTES = 0x3, CLOCK_DESCRIBE_RATES = 0x4, @@ -81,20 +83,20 @@ static int scmi_clock_protocol_attributes_get(const struct scmi_handle *handle, struct scmi_xfer *t; struct scmi_msg_resp_clock_protocol_attributes *attr; - ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES, + ret = ops->xfer_get_init(handle, PROTOCOL_ATTRIBUTES, SCMI_PROTOCOL_CLOCK, 0, sizeof(*attr), &t); if (ret) return ret; attr = t->rx.buf; - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (!ret) { ci->num_clocks = le16_to_cpu(attr->num_clocks); ci->max_async_req = attr->max_async_req; } - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -105,7 +107,7 @@ static int scmi_clock_attributes_get(const struct scmi_handle *handle, struct scmi_xfer *t; struct scmi_msg_resp_clock_attributes *attr; - ret = scmi_xfer_get_init(handle, CLOCK_ATTRIBUTES, SCMI_PROTOCOL_CLOCK, + ret = ops->xfer_get_init(handle, CLOCK_ATTRIBUTES, SCMI_PROTOCOL_CLOCK, sizeof(clk_id), sizeof(*attr), &t); if (ret) return ret; @@ -113,13 +115,13 @@ static int scmi_clock_attributes_get(const struct scmi_handle *handle, put_unaligned_le32(clk_id, t->tx.buf); attr = t->rx.buf; - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (!ret) strlcpy(clk->name, attr->name, SCMI_MAX_STR_SIZE); else clk->name[0] = '\0'; - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -148,7 +150,7 @@ scmi_clock_describe_rates_get(const struct scmi_handle *handle, u32 clk_id, struct scmi_msg_clock_describe_rates *clk_desc; struct scmi_msg_resp_clock_describe_rates *rlist; - ret = scmi_xfer_get_init(handle, CLOCK_DESCRIBE_RATES, + ret = ops->xfer_get_init(handle, CLOCK_DESCRIBE_RATES, SCMI_PROTOCOL_CLOCK, sizeof(*clk_desc), 0, &t); if (ret) return ret; @@ -161,7 +163,7 @@ scmi_clock_describe_rates_get(const struct scmi_handle *handle, u32 clk_id, /* Set the number of rates to be skipped/already read */ clk_desc->rate_index = cpu_to_le32(tot_rate_cnt); - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (ret) goto err; @@ -193,7 +195,7 @@ scmi_clock_describe_rates_get(const struct scmi_handle *handle, u32 clk_id, tot_rate_cnt += num_returned; - scmi_reset_rx_to_maxsz(handle, t); + ops->reset_rx_to_maxsz(handle, t); /* * check for both returned and remaining to avoid infinite * loop due to buggy firmware @@ -208,7 +210,7 @@ scmi_clock_describe_rates_get(const struct scmi_handle *handle, u32 clk_id, clk->rate_discrete = rate_discrete; err: - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -218,18 +220,18 @@ scmi_clock_rate_get(const struct scmi_handle *handle, u32 clk_id, u64 *value) int ret; struct scmi_xfer *t; - ret = scmi_xfer_get_init(handle, CLOCK_RATE_GET, SCMI_PROTOCOL_CLOCK, + ret = ops->xfer_get_init(handle, CLOCK_RATE_GET, SCMI_PROTOCOL_CLOCK, sizeof(__le32), sizeof(u64), &t); if (ret) return ret; put_unaligned_le32(clk_id, t->tx.buf); - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (!ret) *value = get_unaligned_le64(t->rx.buf); - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -241,9 +243,9 @@ static int scmi_clock_rate_set(const struct scmi_handle *handle, u32 clk_id, struct scmi_xfer *t; struct scmi_clock_set_rate *cfg; struct clock_info *ci = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_CLOCK); + ops->get_proto_priv(handle, SCMI_PROTOCOL_CLOCK); - ret = scmi_xfer_get_init(handle, CLOCK_RATE_SET, SCMI_PROTOCOL_CLOCK, + ret = ops->xfer_get_init(handle, CLOCK_RATE_SET, SCMI_PROTOCOL_CLOCK, sizeof(*cfg), 0, &t); if (ret) return ret; @@ -259,14 +261,14 @@ static int scmi_clock_rate_set(const struct scmi_handle *handle, u32 clk_id, cfg->value_high = cpu_to_le32(rate >> 32); if (flags & CLOCK_SET_ASYNC) - ret = scmi_do_xfer_with_response(handle, t); + ret = ops->do_xfer_with_response(handle, t); else - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (ci->max_async_req) atomic_dec(&ci->cur_async_req); - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -277,7 +279,7 @@ scmi_clock_config_set(const struct scmi_handle *handle, u32 clk_id, u32 config) struct scmi_xfer *t; struct scmi_clock_set_config *cfg; - ret = scmi_xfer_get_init(handle, CLOCK_CONFIG_SET, SCMI_PROTOCOL_CLOCK, + ret = ops->xfer_get_init(handle, CLOCK_CONFIG_SET, SCMI_PROTOCOL_CLOCK, sizeof(*cfg), 0, &t); if (ret) return ret; @@ -286,9 +288,9 @@ scmi_clock_config_set(const struct scmi_handle *handle, u32 clk_id, u32 config) cfg->id = cpu_to_le32(clk_id); cfg->attributes = cpu_to_le32(config); - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -305,7 +307,7 @@ static int scmi_clock_disable(const struct scmi_handle *handle, u32 clk_id) static int scmi_clock_count_get(const struct scmi_handle *handle) { struct clock_info *ci = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_CLOCK); + ops->get_proto_priv(handle, SCMI_PROTOCOL_CLOCK); return ci->num_clocks; } @@ -314,7 +316,7 @@ static const struct scmi_clock_info * scmi_clock_info_get(const struct scmi_handle *handle, u32 clk_id) { struct clock_info *ci = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_CLOCK); + ops->get_proto_priv(handle, SCMI_PROTOCOL_CLOCK); struct scmi_clock_info *clk = ci->clk + clk_id; if (!clk->name[0]) @@ -332,13 +334,15 @@ static const struct scmi_clk_ops clk_ops = { .disable = scmi_clock_disable, }; -static int scmi_clock_protocol_init(const struct scmi_handle *handle) +static int scmi_clock_protocol_init(const struct scmi_handle *handle, + const struct scmi_xfer_ops *xops) { u32 version; int clkid, ret; struct clock_info *cinfo; - scmi_version_get(handle, SCMI_PROTOCOL_CLOCK, &version); + ops = xops; + ops->version_get(handle, SCMI_PROTOCOL_CLOCK, &version); dev_dbg(handle->dev, "Clock Version %d.%d\n", PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); @@ -363,7 +367,7 @@ static int scmi_clock_protocol_init(const struct scmi_handle *handle) } cinfo->version = version; - return scmi_set_proto_priv(handle, SCMI_PROTOCOL_CLOCK, cinfo); + return ops->set_proto_priv(handle, SCMI_PROTOCOL_CLOCK, cinfo); } static struct scmi_protocol scmi_clock = { diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 5a91e3324697..ec81edc12ca5 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -145,26 +146,39 @@ struct scmi_xfer { struct completion *async_done; }; -void scmi_xfer_put(const struct scmi_handle *h, struct scmi_xfer *xfer); -int scmi_do_xfer(const struct scmi_handle *h, struct scmi_xfer *xfer); -int scmi_do_xfer_with_response(const struct scmi_handle *h, - struct scmi_xfer *xfer); -int scmi_xfer_get_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id, - size_t tx_size, size_t rx_size, struct scmi_xfer **p); -void scmi_reset_rx_to_maxsz(const struct scmi_handle *handle, - struct scmi_xfer *xfer); +struct scmi_xfer_ops { + int (*version_get)(const struct scmi_handle *handle, u8 protocol, + u32 *version); + int (*set_proto_priv)(const struct scmi_handle *handle, u8 protocol_id, + void *priv); + void *(*get_proto_priv)(const struct scmi_handle *handle, + u8 protocol_id); + int (*xfer_get_init)(const struct scmi_handle *handle, u8 msg_id, + u8 prot_id, size_t tx_size, size_t rx_size, + struct scmi_xfer **p); + void (*reset_rx_to_maxsz)(const struct scmi_handle *handle, + struct scmi_xfer *xfer); + int (*do_xfer)(const struct scmi_handle *handle, + struct scmi_xfer *xfer); + int (*do_xfer_with_response)(const struct scmi_handle *handle, + struct scmi_xfer *xfer); + void (*xfer_put)(const struct scmi_handle *handle, + struct scmi_xfer *xfer); +}; + int scmi_handle_put(const struct scmi_handle *handle); struct scmi_handle *scmi_handle_get(struct device *dev); void scmi_set_handle(struct scmi_device *scmi_dev); -int scmi_version_get(const struct scmi_handle *h, u8 protocol, u32 *version); void scmi_setup_protocol_implemented(const struct scmi_handle *handle, u8 *prot_imp); -typedef int (*scmi_prot_init_fn_t)(const struct scmi_handle *); +typedef int (*scmi_prot_init_fn_t)(const struct scmi_handle *, + const struct scmi_xfer_ops *); /** * struct scmi_protocol - Protocol descriptor * @id: Protocol ID. + * @owner: Module reference if any. * @init: Mandatory protocol initialization function. * @deinit: Optional protocol de-initialization function. * @ops: Optional reference to the operations provided by the protocol and @@ -173,6 +187,7 @@ typedef int (*scmi_prot_init_fn_t)(const struct scmi_handle *); */ struct scmi_protocol { const u8 id; + struct module *owner; const scmi_prot_init_fn_t init; const scmi_prot_init_fn_t deinit; const void *ops; @@ -196,7 +211,7 @@ DECLARE_SCMI_REGISTER_UNREGISTER(system); #define DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(name, proto) \ int __init scmi_##name##_register(void) \ { \ - return scmi_protocol_register(&(proto)); \ + return scmi_protocol_register(&(proto), THIS_MODULE); \ } \ \ void __exit scmi_##name##_unregister(void) \ @@ -205,14 +220,11 @@ void __exit scmi_##name##_unregister(void) \ } const struct scmi_protocol *scmi_get_protocol(int protocol_id); +void scmi_put_protocol(int protocol_id); int scmi_acquire_protocol(const struct scmi_handle *handle, u8 protocol_id); void scmi_release_protocol(const struct scmi_handle *handle, u8 protocol_id); -void *scmi_get_proto_priv(const struct scmi_handle *h, u8 prot); -int scmi_set_proto_priv(const struct scmi_handle *handle, const u8 proto, - void *priv); - /* SCMI Transport */ /** * struct scmi_chan_info - Structure representing a SCMI channel information diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 25a4152537e6..55df134c2338 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -370,7 +370,8 @@ void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr) * @handle: Pointer to SCMI entity handle * @xfer: message that was reserved by scmi_xfer_get */ -void scmi_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer) +static void scmi_xfer_put(const struct scmi_handle *handle, + struct scmi_xfer *xfer) { struct scmi_info *info = handle_to_scmi_info(handle); @@ -398,7 +399,8 @@ static bool scmi_xfer_done_no_timeout(struct scmi_chan_info *cinfo, * return corresponding error, else if all goes well, * return 0. */ -int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer) +static int scmi_do_xfer(const struct scmi_handle *handle, + struct scmi_xfer *xfer) { int ret; int timeout; @@ -451,8 +453,8 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer) return ret; } -void scmi_reset_rx_to_maxsz(const struct scmi_handle *handle, - struct scmi_xfer *xfer) +static void scmi_reset_rx_to_maxsz(const struct scmi_handle *handle, + struct scmi_xfer *xfer) { struct scmi_info *info = handle_to_scmi_info(handle); @@ -471,8 +473,8 @@ void scmi_reset_rx_to_maxsz(const struct scmi_handle *handle, * Return: -ETIMEDOUT in case of no delayed response, if transmit error, * return corresponding error, else if all goes well, return 0. */ -int scmi_do_xfer_with_response(const struct scmi_handle *handle, - struct scmi_xfer *xfer) +static int scmi_do_xfer_with_response(const struct scmi_handle *handle, + struct scmi_xfer *xfer) { int ret, timeout = msecs_to_jiffies(SCMI_MAX_RESPONSE_TIMEOUT); DECLARE_COMPLETION_ONSTACK(async_response); @@ -503,8 +505,9 @@ int scmi_do_xfer_with_response(const struct scmi_handle *handle, * Return: 0 if all went fine with @p pointing to message, else * corresponding error. */ -int scmi_xfer_get_init(const struct scmi_handle *handle, u8 msg_id, u8 prot_id, - size_t tx_size, size_t rx_size, struct scmi_xfer **p) +static int scmi_xfer_get_init(const struct scmi_handle *handle, u8 msg_id, + u8 prot_id, size_t tx_size, size_t rx_size, + struct scmi_xfer **p) { int ret; struct scmi_xfer *xfer; @@ -546,8 +549,8 @@ int scmi_xfer_get_init(const struct scmi_handle *handle, u8 msg_id, u8 prot_id, * * Return: 0 if all went fine, else return appropriate error. */ -int scmi_version_get(const struct scmi_handle *handle, u8 protocol, - u32 *version) +static int scmi_version_get(const struct scmi_handle *handle, u8 protocol, + u32 *version) { int ret; __le32 *rev_info; @@ -568,8 +571,8 @@ int scmi_version_get(const struct scmi_handle *handle, u8 protocol, return ret; } -int scmi_set_proto_priv(const struct scmi_handle *handle, - u8 protocol_id, void *priv) +static int scmi_set_proto_priv(const struct scmi_handle *handle, + u8 protocol_id, void *priv) { struct scmi_info *info = handle_to_scmi_info(handle); @@ -585,7 +588,8 @@ int scmi_set_proto_priv(const struct scmi_handle *handle, return 0; } -void *scmi_get_proto_priv(const struct scmi_handle *handle, u8 protocol_id) +static void *scmi_get_proto_priv(const struct scmi_handle *handle, + u8 protocol_id) { struct scmi_info *info = handle_to_scmi_info(handle); @@ -594,6 +598,17 @@ void *scmi_get_proto_priv(const struct scmi_handle *handle, u8 protocol_id) return info->protocols_private_data[protocol_id]; } +static const struct scmi_xfer_ops xfer_ops = { + .version_get = scmi_version_get, + .set_proto_priv = scmi_set_proto_priv, + .get_proto_priv = scmi_get_proto_priv, + .xfer_get_init = scmi_xfer_get_init, + .reset_rx_to_maxsz = scmi_reset_rx_to_maxsz, + .do_xfer = scmi_do_xfer, + .do_xfer_with_response = scmi_do_xfer_with_response, + .xfer_put = scmi_xfer_put, +}; + /** * scmi_get_protocol_instance - Protocol initialization helper. * @handle: A reference to the SCMI platform instance. @@ -624,7 +639,7 @@ scmi_get_protocol_instance(const struct scmi_handle *handle, u8 protocol_id) /* Fail if protocol not registered on bus */ proto = scmi_get_protocol(protocol_id); if (!proto) { - ret = -EINVAL; + ret = -EPROBE_DEFER; goto out; } @@ -641,7 +656,7 @@ scmi_get_protocol_instance(const struct scmi_handle *handle, u8 protocol_id) pi->proto = proto; refcount_set(&pi->users, 1); /* proto->init is assured NON NULL by scmi_protocol_register */ - ret = pi->proto->init(handle); + ret = pi->proto->init(handle, &xfer_ops); if (ret) goto clean; @@ -664,6 +679,7 @@ scmi_get_protocol_instance(const struct scmi_handle *handle, u8 protocol_id) return pi; clean: + scmi_put_protocol(protocol_id); devres_release_group(handle->dev, gid); out: mutex_unlock(&info->protocols_mtx); @@ -714,13 +730,15 @@ void scmi_release_protocol(const struct scmi_handle *handle, u8 protocol_id) scmi_deregister_protocol_events(handle, protocol_id); if (pi->proto->deinit) - pi->proto->deinit(handle); + pi->proto->deinit(handle, &xfer_ops); info->protocols_private_data[protocol_id] = NULL; info->protocols[protocol_id] = NULL; /* Ensure deinitialized protocol is visible */ smp_wmb(); + scmi_put_protocol(protocol_id); + devres_release_group(handle->dev, gid); dev_dbg(handle->dev, "De-Initialized protocol: 0x%X\n", protocol_id); diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c index b3038362f362..60a28ca39455 100644 --- a/drivers/firmware/arm_scmi/perf.c +++ b/drivers/firmware/arm_scmi/perf.c @@ -19,6 +19,8 @@ #include "common.h" #include "notify.h" +static const struct scmi_xfer_ops *ops; + enum scmi_performance_protocol_cmd { PERF_DOMAIN_ATTRIBUTES = 0x3, PERF_DESCRIBE_LEVELS = 0x4, @@ -182,14 +184,14 @@ static int scmi_perf_attributes_get(const struct scmi_handle *handle, struct scmi_xfer *t; struct scmi_msg_resp_perf_attributes *attr; - ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES, + ret = ops->xfer_get_init(handle, PROTOCOL_ATTRIBUTES, SCMI_PROTOCOL_PERF, 0, sizeof(*attr), &t); if (ret) return ret; attr = t->rx.buf; - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (!ret) { u16 flags = le16_to_cpu(attr->flags); @@ -200,7 +202,7 @@ static int scmi_perf_attributes_get(const struct scmi_handle *handle, pi->stats_size = le32_to_cpu(attr->stats_size); } - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -212,7 +214,7 @@ scmi_perf_domain_attributes_get(const struct scmi_handle *handle, u32 domain, struct scmi_xfer *t; struct scmi_msg_resp_perf_domain_attributes *attr; - ret = scmi_xfer_get_init(handle, PERF_DOMAIN_ATTRIBUTES, + ret = ops->xfer_get_init(handle, PERF_DOMAIN_ATTRIBUTES, SCMI_PROTOCOL_PERF, sizeof(domain), sizeof(*attr), &t); if (ret) @@ -221,7 +223,7 @@ scmi_perf_domain_attributes_get(const struct scmi_handle *handle, u32 domain, put_unaligned_le32(domain, t->tx.buf); attr = t->rx.buf; - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (!ret) { u32 flags = le32_to_cpu(attr->flags); @@ -245,7 +247,7 @@ scmi_perf_domain_attributes_get(const struct scmi_handle *handle, u32 domain, strlcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE); } - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -268,7 +270,7 @@ scmi_perf_describe_levels_get(const struct scmi_handle *handle, u32 domain, struct scmi_msg_perf_describe_levels *dom_info; struct scmi_msg_resp_perf_describe_levels *level_info; - ret = scmi_xfer_get_init(handle, PERF_DESCRIBE_LEVELS, + ret = ops->xfer_get_init(handle, PERF_DESCRIBE_LEVELS, SCMI_PROTOCOL_PERF, sizeof(*dom_info), 0, &t); if (ret) return ret; @@ -281,7 +283,7 @@ scmi_perf_describe_levels_get(const struct scmi_handle *handle, u32 domain, /* Set the number of OPPs to be skipped/already read */ dom_info->level_index = cpu_to_le32(tot_opp_cnt); - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (ret) break; @@ -305,7 +307,7 @@ scmi_perf_describe_levels_get(const struct scmi_handle *handle, u32 domain, tot_opp_cnt += num_returned; - scmi_reset_rx_to_maxsz(handle, t); + ops->reset_rx_to_maxsz(handle, t); /* * check for both returned and remaining to avoid infinite * loop due to buggy firmware @@ -313,7 +315,7 @@ scmi_perf_describe_levels_get(const struct scmi_handle *handle, u32 domain, } while (num_returned && num_remaining); perf_dom->opp_count = tot_opp_cnt; - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); sort(perf_dom->opp, tot_opp_cnt, sizeof(*opp), opp_cmp_func, NULL); return ret; @@ -360,7 +362,7 @@ static int scmi_perf_mb_limits_set(const struct scmi_handle *handle, u32 domain, struct scmi_xfer *t; struct scmi_perf_set_limits *limits; - ret = scmi_xfer_get_init(handle, PERF_LIMITS_SET, SCMI_PROTOCOL_PERF, + ret = ops->xfer_get_init(handle, PERF_LIMITS_SET, SCMI_PROTOCOL_PERF, sizeof(*limits), 0, &t); if (ret) return ret; @@ -370,16 +372,16 @@ static int scmi_perf_mb_limits_set(const struct scmi_handle *handle, u32 domain, limits->max_level = cpu_to_le32(max_perf); limits->min_level = cpu_to_le32(min_perf); - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } static int scmi_perf_limits_set(const struct scmi_handle *handle, u32 domain, u32 max_perf, u32 min_perf) { - struct scmi_perf_info *pi = scmi_get_proto_priv(handle, + struct scmi_perf_info *pi = ops->get_proto_priv(handle, SCMI_PROTOCOL_PERF); struct perf_dom_info *dom = pi->dom_info + domain; @@ -400,14 +402,14 @@ static int scmi_perf_mb_limits_get(const struct scmi_handle *handle, u32 domain, struct scmi_xfer *t; struct scmi_perf_get_limits *limits; - ret = scmi_xfer_get_init(handle, PERF_LIMITS_GET, SCMI_PROTOCOL_PERF, + ret = ops->xfer_get_init(handle, PERF_LIMITS_GET, SCMI_PROTOCOL_PERF, sizeof(__le32), 0, &t); if (ret) return ret; put_unaligned_le32(domain, t->tx.buf); - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (!ret) { limits = t->rx.buf; @@ -415,7 +417,7 @@ static int scmi_perf_mb_limits_get(const struct scmi_handle *handle, u32 domain, *min_perf = le32_to_cpu(limits->min_level); } - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -423,7 +425,7 @@ static int scmi_perf_limits_get(const struct scmi_handle *handle, u32 domain, u32 *max_perf, u32 *min_perf) { struct scmi_perf_info *pi = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_PERF); + ops->get_proto_priv(handle, SCMI_PROTOCOL_PERF); struct perf_dom_info *dom = pi->dom_info + domain; if (dom->fc_info && dom->fc_info->limit_get_addr) { @@ -442,7 +444,7 @@ static int scmi_perf_mb_level_set(const struct scmi_handle *handle, u32 domain, struct scmi_xfer *t; struct scmi_perf_set_level *lvl; - ret = scmi_xfer_get_init(handle, PERF_LEVEL_SET, SCMI_PROTOCOL_PERF, + ret = ops->xfer_get_init(handle, PERF_LEVEL_SET, SCMI_PROTOCOL_PERF, sizeof(*lvl), 0, &t); if (ret) return ret; @@ -452,9 +454,9 @@ static int scmi_perf_mb_level_set(const struct scmi_handle *handle, u32 domain, lvl->domain = cpu_to_le32(domain); lvl->level = cpu_to_le32(level); - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -462,7 +464,7 @@ static int scmi_perf_level_set(const struct scmi_handle *handle, u32 domain, u32 level, bool poll) { struct scmi_perf_info *pi = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_PERF); + ops->get_proto_priv(handle, SCMI_PROTOCOL_PERF); struct perf_dom_info *dom = pi->dom_info + domain; if (dom->fc_info && dom->fc_info->level_set_addr) { @@ -480,7 +482,7 @@ static int scmi_perf_mb_level_get(const struct scmi_handle *handle, u32 domain, int ret; struct scmi_xfer *t; - ret = scmi_xfer_get_init(handle, PERF_LEVEL_GET, SCMI_PROTOCOL_PERF, + ret = ops->xfer_get_init(handle, PERF_LEVEL_GET, SCMI_PROTOCOL_PERF, sizeof(u32), sizeof(u32), &t); if (ret) return ret; @@ -488,11 +490,11 @@ static int scmi_perf_mb_level_get(const struct scmi_handle *handle, u32 domain, t->hdr.poll_completion = poll; put_unaligned_le32(domain, t->tx.buf); - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (!ret) *level = get_unaligned_le32(t->rx.buf); - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -500,7 +502,7 @@ static int scmi_perf_level_get(const struct scmi_handle *handle, u32 domain, u32 *level, bool poll) { struct scmi_perf_info *pi = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_PERF); + ops->get_proto_priv(handle, SCMI_PROTOCOL_PERF); struct perf_dom_info *dom = pi->dom_info + domain; if (dom->fc_info && dom->fc_info->level_get_addr) { @@ -519,7 +521,7 @@ static int scmi_perf_level_limits_notify(const struct scmi_handle *handle, struct scmi_xfer *t; struct scmi_perf_notify_level_or_limits *notify; - ret = scmi_xfer_get_init(handle, message_id, SCMI_PROTOCOL_PERF, + ret = ops->xfer_get_init(handle, message_id, SCMI_PROTOCOL_PERF, sizeof(*notify), 0, &t); if (ret) return ret; @@ -528,9 +530,9 @@ static int scmi_perf_level_limits_notify(const struct scmi_handle *handle, notify->domain = cpu_to_le32(domain); notify->notify_enable = enable ? cpu_to_le32(BIT(0)) : 0; - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -561,7 +563,7 @@ scmi_perf_domain_desc_fc(const struct scmi_handle *handle, u32 domain, if (!p_addr) return; - ret = scmi_xfer_get_init(handle, PERF_DESCRIBE_FASTCHANNEL, + ret = ops->xfer_get_init(handle, PERF_DESCRIBE_FASTCHANNEL, SCMI_PROTOCOL_PERF, sizeof(*info), sizeof(*resp), &t); if (ret) @@ -571,7 +573,7 @@ scmi_perf_domain_desc_fc(const struct scmi_handle *handle, u32 domain, info->domain = cpu_to_le32(domain); info->message_id = cpu_to_le32(message_id); - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (ret) goto err_xfer; @@ -609,7 +611,7 @@ scmi_perf_domain_desc_fc(const struct scmi_handle *handle, u32 domain, *p_db = db; } err_xfer: - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); } static void scmi_perf_domain_init_fc(const struct scmi_handle *handle, @@ -652,7 +654,7 @@ static int scmi_dvfs_device_opps_add(const struct scmi_handle *handle, struct scmi_opp *opp; struct perf_dom_info *dom; struct scmi_perf_info *pi = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_PERF); + ops->get_proto_priv(handle, SCMI_PROTOCOL_PERF); domain = scmi_dev_domain_id(dev); if (domain < 0) @@ -682,7 +684,7 @@ static int scmi_dvfs_transition_latency_get(const struct scmi_handle *handle, { struct perf_dom_info *dom; struct scmi_perf_info *pi = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_PERF); + ops->get_proto_priv(handle, SCMI_PROTOCOL_PERF); int domain = scmi_dev_domain_id(dev); if (domain < 0) @@ -697,7 +699,7 @@ static int scmi_dvfs_freq_set(const struct scmi_handle *handle, u32 domain, unsigned long freq, bool poll) { struct scmi_perf_info *pi = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_PERF); + ops->get_proto_priv(handle, SCMI_PROTOCOL_PERF); struct perf_dom_info *dom = pi->dom_info + domain; return scmi_perf_level_set(handle, domain, freq / dom->mult_factor, @@ -710,7 +712,7 @@ static int scmi_dvfs_freq_get(const struct scmi_handle *handle, u32 domain, int ret; u32 level; struct scmi_perf_info *pi = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_PERF); + ops->get_proto_priv(handle, SCMI_PROTOCOL_PERF); struct perf_dom_info *dom = pi->dom_info + domain; ret = scmi_perf_level_get(handle, domain, &level, poll); @@ -724,7 +726,7 @@ static int scmi_dvfs_est_power_get(const struct scmi_handle *handle, u32 domain, unsigned long *freq, unsigned long *power) { struct scmi_perf_info *pi = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_PERF); + ops->get_proto_priv(handle, SCMI_PROTOCOL_PERF); struct perf_dom_info *dom; unsigned long opp_freq; int idx, ret = -EINVAL; @@ -753,7 +755,7 @@ static bool scmi_fast_switch_possible(const struct scmi_handle *handle, { struct perf_dom_info *dom; struct scmi_perf_info *pi = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_PERF); + ops->get_proto_priv(handle, SCMI_PROTOCOL_PERF); dom = pi->dom_info + scmi_dev_domain_id(dev); @@ -842,7 +844,7 @@ static void *scmi_perf_fill_custom_report(const struct scmi_handle *handle, static int scmi_perf_get_num_sources(const struct scmi_handle *handle) { struct scmi_perf_info *pinfo = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_PERF); + ops->get_proto_priv(handle, SCMI_PROTOCOL_PERF); if (!pinfo) return -EINVAL; @@ -876,13 +878,15 @@ static const struct scmi_protocol_events perf_protocol_events = { .num_events = ARRAY_SIZE(perf_events), }; -static int scmi_perf_protocol_init(const struct scmi_handle *handle) +static int scmi_perf_protocol_init(const struct scmi_handle *handle, + const struct scmi_xfer_ops *xops) { int domain; u32 version; struct scmi_perf_info *pinfo; - scmi_version_get(handle, SCMI_PROTOCOL_PERF, &version); + ops = xops; + ops->version_get(handle, SCMI_PROTOCOL_PERF, &version); dev_dbg(handle->dev, "Performance Version %d.%d\n", PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); @@ -909,7 +913,7 @@ static int scmi_perf_protocol_init(const struct scmi_handle *handle) } pinfo->version = version; - return scmi_set_proto_priv(handle, SCMI_PROTOCOL_PERF, pinfo); + return ops->set_proto_priv(handle, SCMI_PROTOCOL_PERF, pinfo); } static struct scmi_protocol scmi_perf = { diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c index cb9b1f6a56dd..766e1782c9ff 100644 --- a/drivers/firmware/arm_scmi/power.c +++ b/drivers/firmware/arm_scmi/power.c @@ -12,6 +12,8 @@ #include "common.h" #include "notify.h" +static const struct scmi_xfer_ops *ops; + enum scmi_power_protocol_cmd { POWER_DOMAIN_ATTRIBUTES = 0x3, POWER_STATE_SET = 0x4, @@ -75,14 +77,14 @@ static int scmi_power_attributes_get(const struct scmi_handle *handle, struct scmi_xfer *t; struct scmi_msg_resp_power_attributes *attr; - ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES, + ret = ops->xfer_get_init(handle, PROTOCOL_ATTRIBUTES, SCMI_PROTOCOL_POWER, 0, sizeof(*attr), &t); if (ret) return ret; attr = t->rx.buf; - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (!ret) { pi->num_domains = le16_to_cpu(attr->num_domains); pi->stats_addr = le32_to_cpu(attr->stats_addr_low) | @@ -90,7 +92,7 @@ static int scmi_power_attributes_get(const struct scmi_handle *handle, pi->stats_size = le32_to_cpu(attr->stats_size); } - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -102,7 +104,7 @@ scmi_power_domain_attributes_get(const struct scmi_handle *handle, u32 domain, struct scmi_xfer *t; struct scmi_msg_resp_power_domain_attributes *attr; - ret = scmi_xfer_get_init(handle, POWER_DOMAIN_ATTRIBUTES, + ret = ops->xfer_get_init(handle, POWER_DOMAIN_ATTRIBUTES, SCMI_PROTOCOL_POWER, sizeof(domain), sizeof(*attr), &t); if (ret) @@ -111,7 +113,7 @@ scmi_power_domain_attributes_get(const struct scmi_handle *handle, u32 domain, put_unaligned_le32(domain, t->tx.buf); attr = t->rx.buf; - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (!ret) { u32 flags = le32_to_cpu(attr->flags); @@ -121,7 +123,7 @@ scmi_power_domain_attributes_get(const struct scmi_handle *handle, u32 domain, strlcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE); } - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -132,7 +134,7 @@ scmi_power_state_set(const struct scmi_handle *handle, u32 domain, u32 state) struct scmi_xfer *t; struct scmi_power_set_state *st; - ret = scmi_xfer_get_init(handle, POWER_STATE_SET, SCMI_PROTOCOL_POWER, + ret = ops->xfer_get_init(handle, POWER_STATE_SET, SCMI_PROTOCOL_POWER, sizeof(*st), 0, &t); if (ret) return ret; @@ -142,9 +144,9 @@ scmi_power_state_set(const struct scmi_handle *handle, u32 domain, u32 state) st->domain = cpu_to_le32(domain); st->state = cpu_to_le32(state); - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -154,25 +156,25 @@ scmi_power_state_get(const struct scmi_handle *handle, u32 domain, u32 *state) int ret; struct scmi_xfer *t; - ret = scmi_xfer_get_init(handle, POWER_STATE_GET, SCMI_PROTOCOL_POWER, + ret = ops->xfer_get_init(handle, POWER_STATE_GET, SCMI_PROTOCOL_POWER, sizeof(u32), sizeof(u32), &t); if (ret) return ret; put_unaligned_le32(domain, t->tx.buf); - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (!ret) *state = get_unaligned_le32(t->rx.buf); - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } static int scmi_power_num_domains_get(const struct scmi_handle *handle) { struct scmi_power_info *pi = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_POWER); + ops->get_proto_priv(handle, SCMI_PROTOCOL_POWER); return pi->num_domains; } @@ -180,7 +182,7 @@ static int scmi_power_num_domains_get(const struct scmi_handle *handle) static char *scmi_power_name_get(const struct scmi_handle *handle, u32 domain) { struct scmi_power_info *pi = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_POWER); + ops->get_proto_priv(handle, SCMI_PROTOCOL_POWER); struct power_dom_info *dom = pi->dom_info + domain; return dom->name; @@ -200,7 +202,7 @@ static int scmi_power_request_notify(const struct scmi_handle *handle, struct scmi_xfer *t; struct scmi_power_state_notify *notify; - ret = scmi_xfer_get_init(handle, POWER_STATE_NOTIFY, + ret = ops->xfer_get_init(handle, POWER_STATE_NOTIFY, SCMI_PROTOCOL_POWER, sizeof(*notify), 0, &t); if (ret) return ret; @@ -209,9 +211,9 @@ static int scmi_power_request_notify(const struct scmi_handle *handle, notify->domain = cpu_to_le32(domain); notify->notify_enable = enable ? cpu_to_le32(BIT(0)) : 0; - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -251,7 +253,7 @@ static void *scmi_power_fill_custom_report(const struct scmi_handle *handle, static int scmi_power_get_num_sources(const struct scmi_handle *handle) { struct scmi_power_info *pinfo = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_POWER); + ops->get_proto_priv(handle, SCMI_PROTOCOL_POWER); if (!pinfo) return -EINVAL; @@ -281,13 +283,15 @@ static const struct scmi_protocol_events power_protocol_events = { .num_events = ARRAY_SIZE(power_events), }; -static int scmi_power_protocol_init(const struct scmi_handle *handle) +static int scmi_power_protocol_init(const struct scmi_handle *handle, + const struct scmi_xfer_ops *xops) { int domain; u32 version; struct scmi_power_info *pinfo; - scmi_version_get(handle, SCMI_PROTOCOL_POWER, &version); + ops = xops; + ops->version_get(handle, SCMI_PROTOCOL_POWER, &version); dev_dbg(handle->dev, "Power Version %d.%d\n", PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); @@ -310,7 +314,7 @@ static int scmi_power_protocol_init(const struct scmi_handle *handle) } pinfo->version = version; - return scmi_set_proto_priv(handle, SCMI_PROTOCOL_POWER, pinfo); + return ops->set_proto_priv(handle, SCMI_PROTOCOL_POWER, pinfo); } static struct scmi_protocol scmi_power = { diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c index 83bfd0514d4d..9accad66e07e 100644 --- a/drivers/firmware/arm_scmi/reset.c +++ b/drivers/firmware/arm_scmi/reset.c @@ -12,6 +12,8 @@ #include "common.h" #include "notify.h" +static const struct scmi_xfer_ops *ops; + enum scmi_reset_protocol_cmd { RESET_DOMAIN_ATTRIBUTES = 0x3, RESET = 0x4, @@ -71,18 +73,18 @@ static int scmi_reset_attributes_get(const struct scmi_handle *handle, struct scmi_xfer *t; u32 attr; - ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES, + ret = ops->xfer_get_init(handle, PROTOCOL_ATTRIBUTES, SCMI_PROTOCOL_RESET, 0, sizeof(attr), &t); if (ret) return ret; - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (!ret) { attr = get_unaligned_le32(t->rx.buf); pi->num_domains = attr & NUM_RESET_DOMAIN_MASK; } - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -94,7 +96,7 @@ scmi_reset_domain_attributes_get(const struct scmi_handle *handle, u32 domain, struct scmi_xfer *t; struct scmi_msg_resp_reset_domain_attributes *attr; - ret = scmi_xfer_get_init(handle, RESET_DOMAIN_ATTRIBUTES, + ret = ops->xfer_get_init(handle, RESET_DOMAIN_ATTRIBUTES, SCMI_PROTOCOL_RESET, sizeof(domain), sizeof(*attr), &t); if (ret) @@ -103,7 +105,7 @@ scmi_reset_domain_attributes_get(const struct scmi_handle *handle, u32 domain, put_unaligned_le32(domain, t->tx.buf); attr = t->rx.buf; - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (!ret) { u32 attributes = le32_to_cpu(attr->attributes); @@ -115,14 +117,14 @@ scmi_reset_domain_attributes_get(const struct scmi_handle *handle, u32 domain, strlcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE); } - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } static int scmi_reset_num_domains_get(const struct scmi_handle *handle) { struct scmi_reset_info *pi = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_RESET); + ops->get_proto_priv(handle, SCMI_PROTOCOL_RESET); return pi->num_domains; } @@ -130,7 +132,7 @@ static int scmi_reset_num_domains_get(const struct scmi_handle *handle) static char *scmi_reset_name_get(const struct scmi_handle *handle, u32 domain) { struct scmi_reset_info *pi = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_RESET); + ops->get_proto_priv(handle, SCMI_PROTOCOL_RESET); struct reset_dom_info *dom = pi->dom_info + domain; return dom->name; @@ -139,7 +141,7 @@ static char *scmi_reset_name_get(const struct scmi_handle *handle, u32 domain) static int scmi_reset_latency_get(const struct scmi_handle *handle, u32 domain) { struct scmi_reset_info *pi = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_RESET); + ops->get_proto_priv(handle, SCMI_PROTOCOL_RESET); struct reset_dom_info *dom = pi->dom_info + domain; return dom->latency_us; @@ -152,13 +154,13 @@ static int scmi_domain_reset(const struct scmi_handle *handle, u32 domain, struct scmi_xfer *t; struct scmi_msg_reset_domain_reset *dom; struct scmi_reset_info *pi = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_RESET); + ops->get_proto_priv(handle, SCMI_PROTOCOL_RESET); struct reset_dom_info *rdom = pi->dom_info + domain; if (rdom->async_reset) flags |= ASYNCHRONOUS_RESET; - ret = scmi_xfer_get_init(handle, RESET, SCMI_PROTOCOL_RESET, + ret = ops->xfer_get_init(handle, RESET, SCMI_PROTOCOL_RESET, sizeof(*dom), 0, &t); if (ret) return ret; @@ -169,11 +171,11 @@ static int scmi_domain_reset(const struct scmi_handle *handle, u32 domain, dom->reset_state = cpu_to_le32(state); if (rdom->async_reset) - ret = scmi_do_xfer_with_response(handle, t); + ret = ops->do_xfer_with_response(handle, t); else - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -213,7 +215,7 @@ static int scmi_reset_notify(const struct scmi_handle *handle, u32 domain_id, struct scmi_xfer *t; struct scmi_msg_reset_notify *cfg; - ret = scmi_xfer_get_init(handle, RESET_NOTIFY, + ret = ops->xfer_get_init(handle, RESET_NOTIFY, SCMI_PROTOCOL_RESET, sizeof(*cfg), 0, &t); if (ret) return ret; @@ -222,9 +224,9 @@ static int scmi_reset_notify(const struct scmi_handle *handle, u32 domain_id, cfg->id = cpu_to_le32(domain_id); cfg->event_control = cpu_to_le32(evt_cntl); - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -264,7 +266,7 @@ static void *scmi_reset_fill_custom_report(const struct scmi_handle *handle, static int scmi_reset_get_num_sources(const struct scmi_handle *handle) { struct scmi_reset_info *pinfo = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_RESET); + ops->get_proto_priv(handle, SCMI_PROTOCOL_RESET); if (!pinfo) return -EINVAL; @@ -293,13 +295,15 @@ static const struct scmi_protocol_events reset_protocol_events = { .num_events = ARRAY_SIZE(reset_events), }; -static int scmi_reset_protocol_init(const struct scmi_handle *handle) +static int scmi_reset_protocol_init(const struct scmi_handle *handle, + const struct scmi_xfer_ops *xops) { int domain; u32 version; struct scmi_reset_info *pinfo; - scmi_version_get(handle, SCMI_PROTOCOL_RESET, &version); + ops = xops; + ops->version_get(handle, SCMI_PROTOCOL_RESET, &version); dev_dbg(handle->dev, "Reset Version %d.%d\n", PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); @@ -322,7 +326,7 @@ static int scmi_reset_protocol_init(const struct scmi_handle *handle) } pinfo->version = version; - return scmi_set_proto_priv(handle, SCMI_PROTOCOL_RESET, pinfo); + return ops->set_proto_priv(handle, SCMI_PROTOCOL_RESET, pinfo); } static struct scmi_protocol scmi_reset = { diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c index 79bdd53ab7ba..3a58dbca2b70 100644 --- a/drivers/firmware/arm_scmi/sensors.c +++ b/drivers/firmware/arm_scmi/sensors.c @@ -12,6 +12,8 @@ #include "common.h" #include "notify.h" +static const struct scmi_xfer_ops *ops; + enum scmi_sensor_protocol_cmd { SENSOR_DESCRIPTION_GET = 0x3, SENSOR_TRIP_POINT_NOTIFY = 0x4, @@ -94,14 +96,14 @@ static int scmi_sensor_attributes_get(const struct scmi_handle *handle, struct scmi_xfer *t; struct scmi_msg_resp_sensor_attributes *attr; - ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES, + ret = ops->xfer_get_init(handle, PROTOCOL_ATTRIBUTES, SCMI_PROTOCOL_SENSOR, 0, sizeof(*attr), &t); if (ret) return ret; attr = t->rx.buf; - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (!ret) { si->num_sensors = le16_to_cpu(attr->num_sensors); si->max_requests = attr->max_requests; @@ -110,7 +112,7 @@ static int scmi_sensor_attributes_get(const struct scmi_handle *handle, si->reg_size = le32_to_cpu(attr->reg_size); } - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -123,7 +125,7 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle, struct scmi_xfer *t; struct scmi_msg_resp_sensor_description *buf; - ret = scmi_xfer_get_init(handle, SENSOR_DESCRIPTION_GET, + ret = ops->xfer_get_init(handle, SENSOR_DESCRIPTION_GET, SCMI_PROTOCOL_SENSOR, sizeof(__le32), 0, &t); if (ret) return ret; @@ -134,7 +136,7 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle, /* Set the number of sensors to be skipped/already read */ put_unaligned_le32(desc_index, t->tx.buf); - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (ret) break; @@ -167,14 +169,14 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle, desc_index += num_returned; - scmi_reset_rx_to_maxsz(handle, t); + ops->reset_rx_to_maxsz(handle, t); /* * check for both returned and remaining to avoid infinite * loop due to buggy firmware */ } while (num_returned && num_remaining); - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -186,7 +188,7 @@ static int scmi_sensor_trip_point_notify(const struct scmi_handle *handle, struct scmi_xfer *t; struct scmi_msg_sensor_trip_point_notify *cfg; - ret = scmi_xfer_get_init(handle, SENSOR_TRIP_POINT_NOTIFY, + ret = ops->xfer_get_init(handle, SENSOR_TRIP_POINT_NOTIFY, SCMI_PROTOCOL_SENSOR, sizeof(*cfg), 0, &t); if (ret) return ret; @@ -195,9 +197,9 @@ static int scmi_sensor_trip_point_notify(const struct scmi_handle *handle, cfg->id = cpu_to_le32(sensor_id); cfg->event_control = cpu_to_le32(evt_cntl); - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -210,7 +212,7 @@ scmi_sensor_trip_point_config(const struct scmi_handle *handle, u32 sensor_id, struct scmi_xfer *t; struct scmi_msg_set_sensor_trip_point *trip; - ret = scmi_xfer_get_init(handle, SENSOR_TRIP_POINT_CONFIG, + ret = ops->xfer_get_init(handle, SENSOR_TRIP_POINT_CONFIG, SCMI_PROTOCOL_SENSOR, sizeof(*trip), 0, &t); if (ret) return ret; @@ -221,9 +223,9 @@ scmi_sensor_trip_point_config(const struct scmi_handle *handle, u32 sensor_id, trip->value_low = cpu_to_le32(trip_value & 0xffffffff); trip->value_high = cpu_to_le32(trip_value >> 32); - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -234,10 +236,10 @@ static int scmi_sensor_reading_get(const struct scmi_handle *handle, struct scmi_xfer *t; struct scmi_msg_sensor_reading_get *sensor; struct sensors_info *si = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_SENSOR); + ops->get_proto_priv(handle, SCMI_PROTOCOL_SENSOR); struct scmi_sensor_info *s = si->sensors + sensor_id; - ret = scmi_xfer_get_init(handle, SENSOR_READING_GET, + ret = ops->xfer_get_init(handle, SENSOR_READING_GET, SCMI_PROTOCOL_SENSOR, sizeof(*sensor), sizeof(u64), &t); if (ret) @@ -248,18 +250,18 @@ static int scmi_sensor_reading_get(const struct scmi_handle *handle, if (s->async) { sensor->flags = cpu_to_le32(SENSOR_READ_ASYNC); - ret = scmi_do_xfer_with_response(handle, t); + ret = ops->do_xfer_with_response(handle, t); if (!ret) *value = get_unaligned_le64((void *) ((__le32 *)t->rx.buf + 1)); } else { sensor->flags = cpu_to_le32(0); - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); if (!ret) *value = get_unaligned_le64(t->rx.buf); } - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -267,7 +269,7 @@ static const struct scmi_sensor_info * scmi_sensor_info_get(const struct scmi_handle *handle, u32 sensor_id) { struct sensors_info *si = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_SENSOR); + ops->get_proto_priv(handle, SCMI_PROTOCOL_SENSOR); return si->sensors + sensor_id; } @@ -275,7 +277,7 @@ scmi_sensor_info_get(const struct scmi_handle *handle, u32 sensor_id) static int scmi_sensor_count_get(const struct scmi_handle *handle) { struct sensors_info *si = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_SENSOR); + ops->get_proto_priv(handle, SCMI_PROTOCOL_SENSOR); return si->num_sensors; } @@ -324,7 +326,7 @@ static void *scmi_sensor_fill_custom_report(const struct scmi_handle *handle, static int scmi_sensor_get_num_sources(const struct scmi_handle *handle) { struct sensors_info *sinfo = - scmi_get_proto_priv(handle, SCMI_PROTOCOL_SENSOR); + ops->get_proto_priv(handle, SCMI_PROTOCOL_SENSOR); if (!sinfo) return -EINVAL; @@ -353,12 +355,14 @@ static const struct scmi_protocol_events sensor_protocol_events = { .num_events = ARRAY_SIZE(sensor_events), }; -static int scmi_sensors_protocol_init(const struct scmi_handle *handle) +static int scmi_sensors_protocol_init(const struct scmi_handle *handle, + const struct scmi_xfer_ops *xops) { u32 version; struct sensors_info *sinfo; - scmi_version_get(handle, SCMI_PROTOCOL_SENSOR, &version); + ops = xops; + ops->version_get(handle, SCMI_PROTOCOL_SENSOR, &version); dev_dbg(handle->dev, "Sensor Version %d.%d\n", PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); @@ -377,7 +381,7 @@ static int scmi_sensors_protocol_init(const struct scmi_handle *handle) scmi_sensor_description_get(handle, sinfo); sinfo->version = version; - return scmi_set_proto_priv(handle, SCMI_PROTOCOL_SENSOR, sinfo); + return ops->set_proto_priv(handle, SCMI_PROTOCOL_SENSOR, sinfo); } static struct scmi_protocol scmi_sensors = { diff --git a/drivers/firmware/arm_scmi/system.c b/drivers/firmware/arm_scmi/system.c index ae884fc669f5..4db3cc9cea3b 100644 --- a/drivers/firmware/arm_scmi/system.c +++ b/drivers/firmware/arm_scmi/system.c @@ -14,6 +14,8 @@ #define SCMI_SYSTEM_NUM_SOURCES 1 +static const struct scmi_xfer_ops *ops; + enum scmi_system_protocol_cmd { SYSTEM_POWER_STATE_NOTIFY = 0x5, }; @@ -39,7 +41,7 @@ static int scmi_system_request_notify(const struct scmi_handle *handle, struct scmi_xfer *t; struct scmi_system_power_state_notify *notify; - ret = scmi_xfer_get_init(handle, SYSTEM_POWER_STATE_NOTIFY, + ret = ops->xfer_get_init(handle, SYSTEM_POWER_STATE_NOTIFY, SCMI_PROTOCOL_SYSTEM, sizeof(*notify), 0, &t); if (ret) return ret; @@ -47,9 +49,9 @@ static int scmi_system_request_notify(const struct scmi_handle *handle, notify = t->tx.buf; notify->notify_enable = enable ? cpu_to_le32(BIT(0)) : 0; - ret = scmi_do_xfer(handle, t); + ret = ops->do_xfer(handle, t); - scmi_xfer_put(handle, t); + ops->xfer_put(handle, t); return ret; } @@ -109,12 +111,14 @@ static const struct scmi_protocol_events system_protocol_events = { .num_sources = SCMI_SYSTEM_NUM_SOURCES, }; -static int scmi_system_protocol_init(const struct scmi_handle *handle) +static int scmi_system_protocol_init(const struct scmi_handle *handle, + const struct scmi_xfer_ops *xops) { u32 version; struct scmi_system_info *pinfo; - scmi_version_get(handle, SCMI_PROTOCOL_SYSTEM, &version); + ops = xops; + ops->version_get(handle, SCMI_PROTOCOL_SYSTEM, &version); dev_dbg(handle->dev, "System Power Version %d.%d\n", PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); @@ -124,7 +128,7 @@ static int scmi_system_protocol_init(const struct scmi_handle *handle) return -ENOMEM; pinfo->version = version; - return scmi_set_proto_priv(handle, SCMI_PROTOCOL_SYSTEM, pinfo); + return ops->set_proto_priv(handle, SCMI_PROTOCOL_SYSTEM, pinfo); } static struct scmi_protocol scmi_system = { diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 650d0877a5c8..da675d6f90c0 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -351,8 +351,24 @@ static inline void scmi_driver_unregister(struct scmi_driver *driver) {} #define module_scmi_driver(__scmi_driver) \ module_driver(__scmi_driver, scmi_register, scmi_unregister) +#define scmi_load(proto) \ + scmi_protocol_register(proto, THIS_MODULE) +#define scmi_unload(proto) \ + scmi_protocol_unregister(proto) + +/** + * module_scmi_protocol() - Helper macro for registering a scmi protocol + * @__scmi_protocol: scmi_protocol structure + * + * Helper macro for scmi drivers to set up proper module init / exit + * functions. Replaces module_init() and module_exit() and keeps people from + * printing pointless things to the kernel log when their driver is loaded. + */ +#define module_scmi_protocol(__scmi_protocol) \ + module_driver(__scmi_protocol, scmi_load, scmi_unload) + struct scmi_protocol; -int scmi_protocol_register(struct scmi_protocol *proto); +int scmi_protocol_register(struct scmi_protocol *proto, struct module *owner); void scmi_protocol_unregister(const struct scmi_protocol *proto); /* SCMI Notification API - Custom Event Reports */ From patchwork Wed Oct 14 15:05:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11837839 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 B106F61C for ; Wed, 14 Oct 2020 15:07:56 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (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 5F66921582 for ; Wed, 14 Oct 2020 15:07:56 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="2gUrKyW+" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5F66921582 Authentication-Results: mail.kernel.org; dmarc=fail (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=merlin.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=2MYzW9Uil3qPXbjNP9ASKZ/+jf057Qj+YeJA3wSx2IE=; b=2gUrKyW+tI1no2ey22Ht2di2p5 mlPbMu6lHuL0kyn1dc43e8CD33efzFdCHyd9mjQWJoXsIQt5JZ42SnW5IBSHjgcD5DDeYItmg8AU6 dhaTHYIAZp6lRm2yDnda90oABol95jl/zW4rD9REsfuhEHukx9EY/lMexe3pxX5p4cQwUgcNfSHlA yVwma/2vrhsa69nLXe+CDVTdGZdss3YMauSSBaVYA4cJATmPCz5d5THp9GCH3fn1oqKqHW4NolAwO 11ed8VqC4wfgzfow2wuD3TBgNHOpDP23WdG2yDdCq8J1L25Dgvcb9ZkMlKG249TlybVf8zb61YRQY 6t9teSQQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kSiNN-0001WN-Or; Wed, 14 Oct 2020 15:07:37 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kSiMs-0001LU-TD for linux-arm-kernel@lists.infradead.org; Wed, 14 Oct 2020 15:07:10 +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 88647D6E; Wed, 14 Oct 2020 08:07:06 -0700 (PDT) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id DE49D3F71F; Wed, 14 Oct 2020 08:07:04 -0700 (PDT) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH 07/11] [DEBUG] firmware: arm_scmi: add example custom protocol Date: Wed, 14 Oct 2020 16:05:41 +0100 Message-Id: <20201014150545.44807-8-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201014150545.44807-1-cristian.marussi@arm.com> References: <20201014150545.44807-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201014_110707_087775_680D0EEC X-CRM114-Status: GOOD ( 22.26 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.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: f.fainelli@gmail.com, vincent.guittot@linaro.org, sudeep.holla@arm.com, thara.gopinath@linaro.org, cristian.marussi@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, souvik.chakravarty@arm.com, etienne.carriere@linaro.org, lukasz.luba@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 support for a loadable module implementing a custom vendor protocol just as an example. Signed-off-by: Cristian Marussi --- drivers/firmware/Kconfig | 10 +- drivers/firmware/arm_scmi/Makefile | 3 + drivers/firmware/arm_scmi/scmi_custom.c | 170 ++++++++++++++++++++++++ include/linux/scmi_protocol.h | 21 +++ 4 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/arm_scmi/scmi_custom.c diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index afdbebba628a..75e2668a6490 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -6,7 +6,7 @@ menu "Firmware Drivers" -config ARM_SCMI_PROTOCOL +menuconfig ARM_SCMI_PROTOCOL tristate "ARM System Control and Management Interface (SCMI) Message Protocol" depends on ARM || ARM64 || COMPILE_TEST depends on MAILBOX @@ -27,6 +27,14 @@ config ARM_SCMI_PROTOCOL This protocol library provides interface for all the client drivers making use of the features offered by the SCMI. +if ARM_SCMI_PROTOCOL + config ARM_SCMI_PROTOCOL_CUSTOM + tristate "SCMI Custom Protocol Implementation" + default y + help + ARM SCMI System Custom Protocol implementation +endif + config ARM_SCMI_POWER_DOMAIN tristate "SCMI power domain driver" depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF) diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile index bc0d54f8e861..0a03b7432497 100644 --- a/drivers/firmware/arm_scmi/Makefile +++ b/drivers/firmware/arm_scmi/Makefile @@ -7,5 +7,8 @@ scmi-transport-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) += smc.o scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o system.o scmi-module-objs := $(scmi-bus-y) $(scmi-driver-y) $(scmi-protocols-y) \ $(scmi-transport-y) + +obj-$(CONFIG_ARM_SCMI_PROTOCOL_CUSTOM) += scmi_custom.o + obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-module.o obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o diff --git a/drivers/firmware/arm_scmi/scmi_custom.c b/drivers/firmware/arm_scmi/scmi_custom.c new file mode 100644 index 000000000000..5dfdbd175043 --- /dev/null +++ b/drivers/firmware/arm_scmi/scmi_custom.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * System Control and Management Interface (SCMI) Dummy Custom Protocol + * + * Copyright (C) 2018-2020 ARM Ltd. + */ + +#define pr_fmt(fmt) "SCMI Notifications CUSTOM - " fmt + +#include + +#include "common.h" +#include "notify.h" + +static const struct scmi_xfer_ops *ops; + +struct scmi_dummy_scream_notify_payld { + __le32 agent_id; + __le32 domain_id; + __le32 scream; +}; + +struct dummy_dom_info { + bool state_set_sync; + bool state_set_async; + bool state_set_notify; + char name[SCMI_MAX_STR_SIZE]; +}; + +struct scmi_dummy_info { + u32 version; + int num_domains; + u64 stats_addr; + u32 stats_size; + struct dummy_dom_info *dom_info; +}; + +static int scmi_dummy_num_domains_get(const struct scmi_handle *handle) +{ + struct scmi_dummy_info *di = + ops->get_proto_priv(handle, SCMI_PROTOCOL_CUSTOM_DUMMY); + + return di->num_domains; +} + +static const struct scmi_dummy_ops dummy_ops = { + .num_domains_get = scmi_dummy_num_domains_get, +}; + +static int scmi_dummy_request_notify(const struct scmi_handle *handle, + u32 domain, bool enable) +{ + return domain % 2; +} + +static int scmi_dummy_set_notify_enabled(const struct scmi_handle *handle, + u8 evt_id, u32 src_id, bool enable) +{ + int ret; + + ret = scmi_dummy_request_notify(handle, src_id, enable); + if (ret) + pr_debug("FAIL_ENABLE - evt[%X] dom[%d] - ret:%d\n", + evt_id, src_id, ret); + else + pr_warn("NOTIF %sABLED - evt[%X] dom[%d]\n", + enable ? "EN" : "DIS", evt_id, src_id); + + return ret; +} + +static void *scmi_dummy_fill_custom_report(const struct scmi_handle *handle, + u8 evt_id, ktime_t timestamp, + const void *payld, size_t payld_sz, + void *report, u32 *src_id) +{ + const struct scmi_dummy_scream_notify_payld *p = payld; + struct scmi_dummy_scream_report *r = report; + + if (evt_id != SCMI_EVENT_DUMMY_SCREAM || sizeof(*p) != payld_sz) + return NULL; + + r->timestamp = timestamp; + r->agent_id = le32_to_cpu(p->agent_id); + r->domain_id = le32_to_cpu(p->domain_id); + r->scream = le32_to_cpu(p->scream); + *src_id = r->domain_id; + + return r; +} + +static int scmi_dummy_get_num_sources(const struct scmi_handle *handle) +{ + struct scmi_dummy_info *dinfo = + ops->get_proto_priv(handle, SCMI_PROTOCOL_CUSTOM_DUMMY); + + if (!dinfo) + return -EINVAL; + + return dinfo->num_domains; +} + +static const struct scmi_event dummy_events[] = { + { + .id = SCMI_EVENT_DUMMY_SCREAM, + .max_payld_sz = sizeof(struct scmi_dummy_scream_notify_payld), + .max_report_sz = + sizeof(struct scmi_dummy_scream_report), + }, +}; + +static const struct scmi_event_ops dummy_event_ops = { + .get_num_sources = scmi_dummy_get_num_sources, + .set_notify_enabled = scmi_dummy_set_notify_enabled, + .fill_custom_report = scmi_dummy_fill_custom_report, +}; + +static const struct scmi_protocol_events dummy_protocol_events = { + .queue_sz = SCMI_PROTO_QUEUE_SZ, + .ops = &dummy_event_ops, + .evts = dummy_events, + .num_events = ARRAY_SIZE(dummy_events), +}; + +static int scmi_dummy_protocol_init(const struct scmi_handle *handle, + const struct scmi_xfer_ops *xops) +{ + u32 version = 0x20000001; + struct scmi_dummy_info *dinfo; + + ops = xops; + //ops->version_get(handle, SCMI_PROTOCOL_POWER, &version); + + dev_dbg(handle->dev, "Dummy Custom Version %d.%d\n", + PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); + + dinfo = devm_kzalloc(handle->dev, sizeof(*dinfo), GFP_KERNEL); + if (!dinfo) + return -ENOMEM; + + dinfo->num_domains = 5; + + dinfo->dom_info = devm_kcalloc(handle->dev, dinfo->num_domains, + sizeof(*dinfo->dom_info), GFP_KERNEL); + if (!dinfo->dom_info) + return -ENOMEM; + + dinfo->version = version; + return ops->set_proto_priv(handle, SCMI_PROTOCOL_CUSTOM_DUMMY, dinfo); +} + +static int scmi_dummy_protocol_deinit(const struct scmi_handle *handle, + const struct scmi_xfer_ops *xops) +{ + return 0; +} + +static struct scmi_protocol scmi_custom = { + .id = SCMI_PROTOCOL_CUSTOM_DUMMY, + .init = &scmi_dummy_protocol_init, + .deinit = &scmi_dummy_protocol_deinit, + .ops = &dummy_ops, + .events = &dummy_protocol_events, +}; + +module_scmi_protocol(scmi_custom); + +MODULE_AUTHOR("DummyMaster"); +MODULE_DESCRIPTION("ARM SCMI Custom Dummy Protocol"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index da675d6f90c0..9a89ca68b27d 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -209,6 +209,12 @@ struct scmi_reset_ops { int (*deassert)(const struct scmi_handle *handle, u32 domain); }; +#if IS_ENABLED(CONFIG_ARM_SCMI_PROTOCOL_CUSTOM) +struct scmi_dummy_ops { + int (*num_domains_get)(const struct scmi_handle *handle); +}; +#endif + /** * struct scmi_notify_ops - represents notifications' operations provided by * SCMI core @@ -278,6 +284,9 @@ enum scmi_std_protocol { SCMI_PROTOCOL_CLOCK = 0x14, SCMI_PROTOCOL_SENSOR = 0x15, SCMI_PROTOCOL_RESET = 0x16, +#if IS_ENABLED(CONFIG_ARM_SCMI_PROTOCOL_CUSTOM) + SCMI_PROTOCOL_CUSTOM_DUMMY = 0x99, +#endif }; enum scmi_system_events { @@ -380,6 +389,9 @@ enum scmi_notification_events { SCMI_EVENT_RESET_ISSUED = 0x0, SCMI_EVENT_BASE_ERROR_EVENT = 0x0, SCMI_EVENT_SYSTEM_POWER_STATE_NOTIFIER = 0x0, +#if IS_ENABLED(CONFIG_ARM_SCMI_PROTOCOL_CUSTOM) + SCMI_EVENT_DUMMY_SCREAM = 0x0, +#endif }; struct scmi_power_state_changed_report { @@ -433,4 +445,13 @@ struct scmi_base_error_report { unsigned long long reports[]; }; +#if IS_ENABLED(CONFIG_ARM_SCMI_PROTOCOL_CUSTOM) +struct scmi_dummy_scream_report { + ktime_t timestamp; + unsigned int agent_id; + unsigned int domain_id; + unsigned int scream; +}; +#endif + #endif /* _LINUX_SCMI_PROTOCOL_H */ From patchwork Wed Oct 14 15:05:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11837853 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 A315E921 for ; Wed, 14 Oct 2020 15:09:35 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (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 6290F22201 for ; Wed, 14 Oct 2020 15:09:35 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="MNsxJwBH" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6290F22201 Authentication-Results: mail.kernel.org; dmarc=fail (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=merlin.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=psxqQzE04XUCzUVYlmzOkXiltlvMRjN7c6Du+GwMV/U=; b=MNsxJwBHsi9YI3eYkN9SRZ0tcV wypvYK5bkrJpFk8Hnihyisb/HV9W18N2zk+vjE2qJaBsmq0VbWAI/sSJBtR3lBfnM+tg9dgmsh5eh kIOfodQihQ68uJon9ApdFzuxVYANyJNcdJtutcKHZmw0srlwgaIy/3NreDcAVX97HNcGAV+QaQDAW DKQ+Bcy+MTCK5aOqG8Urw7KFbPLJXCuz+GUBCaO9+f3Zkg1UP5L/vqx/LjxUWB8UlUaQxayhIqJfq e/G7TjiZpKjTf9IjV8tSU1/CPgZTwldjk15xNeGH6V49/Gh+GIgff1aQuJSFWLSipHt1oWgRXvKYY 67rgxuyg==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kSiNY-0001ZS-Bz; Wed, 14 Oct 2020 15:07:48 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kSiMv-0001M1-32 for linux-arm-kernel@lists.infradead.org; Wed, 14 Oct 2020 15:07:12 +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 7127913D5; Wed, 14 Oct 2020 08:07:08 -0700 (PDT) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id C04583F71F; Wed, 14 Oct 2020 08:07:06 -0700 (PDT) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH 08/11] [DEBUG] arm64: dts: juno: add example custom protocol support Date: Wed, 14 Oct 2020 16:05:42 +0100 Message-Id: <20201014150545.44807-9-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201014150545.44807-1-cristian.marussi@arm.com> References: <20201014150545.44807-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201014_110709_253659_26F155C3 X-CRM114-Status: GOOD ( 10.33 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.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: f.fainelli@gmail.com, vincent.guittot@linaro.org, sudeep.holla@arm.com, thara.gopinath@linaro.org, cristian.marussi@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, souvik.chakravarty@arm.com, etienne.carriere@linaro.org, lukasz.luba@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 an example custom protocol 0x99 support. Signed-off-by: Cristian Marussi --- arch/arm64/boot/dts/arm/juno-base.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/arm/juno-base.dtsi b/arch/arm64/boot/dts/arm/juno-base.dtsi index dd20a5242c45..85a45a536bbf 100644 --- a/arch/arm64/boot/dts/arm/juno-base.dtsi +++ b/arch/arm64/boot/dts/arm/juno-base.dtsi @@ -598,6 +598,10 @@ reg = <0x15>; #thermal-sensor-cells = <1>; }; + + scmi_custom99: protocol@99 { + reg = <0x99>; + }; }; }; From patchwork Wed Oct 14 15:05:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11837841 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 523F361C for ; Wed, 14 Oct 2020 15:08:18 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (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 1449C22203 for ; Wed, 14 Oct 2020 15:08:18 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="aLUweq5G" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1449C22203 Authentication-Results: mail.kernel.org; dmarc=fail (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=merlin.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=D8m4FWL2ncAsXKLn3wvHzyMgrAd4gV7MsDzPaoaGgyY=; b=aLUweq5GeXWtCAgZMWRauP9stc L6An15ncKewMt3fvbtVzeYbJw7nrI73MnqzQ5jUdhTCkmeUPFPYBaLy9mvQlv5eTPyCdHWXcz+YzD axrKmPP5+MUcyCbpChGjbbmz6OtPikxIdpjwt5g4yE90COx9khAuq40ygxxs8UFftHHemdl9AWBsh T+EnSSiFtetBLtIc1MvKb9x1IivAT6DluyduCQhfrf8INC+k9oLiFS3RAKarArxQRcmH/PmLVdSr3 nYnkloTg8I02vZVr/cv/CvupBUa+wzDHleu+/rijuIfqcm+5uUGKzqPOwm34/vt+2DJJSc4sRwfCq xk1PyK+g==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kSiNo-0001ed-LV; Wed, 14 Oct 2020 15:08:04 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kSiMw-0001Mi-Vg for linux-arm-kernel@lists.infradead.org; Wed, 14 Oct 2020 15:07:14 +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 97A7DD6E; Wed, 14 Oct 2020 08:07:10 -0700 (PDT) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id A77323F71F; Wed, 14 Oct 2020 08:07:08 -0700 (PDT) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH 09/11] [DEBUG] firmware: arm_scmi: add example SCMI driver for custom protocol Date: Wed, 14 Oct 2020 16:05:43 +0100 Message-Id: <20201014150545.44807-10-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201014150545.44807-1-cristian.marussi@arm.com> References: <20201014150545.44807-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201014_110711_175362_49A762CF X-CRM114-Status: GOOD ( 19.64 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.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: f.fainelli@gmail.com, vincent.guittot@linaro.org, sudeep.holla@arm.com, thara.gopinath@linaro.org, cristian.marussi@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, souvik.chakravarty@arm.com, etienne.carriere@linaro.org, lukasz.luba@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 an example SCMI driver using custom vendor protocol 0x99 and also registering for Performance protocol notifications. Signed-off-by: Cristian Marussi --- drivers/firmware/Kconfig | 7 + drivers/firmware/arm_scmi/Makefile | 2 + drivers/firmware/arm_scmi/scmi_custom_dummy.c | 126 ++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 drivers/firmware/arm_scmi/scmi_custom_dummy.c diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 75e2668a6490..d209df6fd3ee 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -48,6 +48,13 @@ config ARM_SCMI_POWER_DOMAIN will be called scmi_pm_domain. Note this may needed early in boot before rootfs may be available. +config ARM_SCMI_CUSTOM_DUMMY + tristate "SCMI Custom Dummy driver" + depends on ARM_SCMI_PROTOCOL_CUSTOM || (COMPILE_TEST && OF) + default n + help + Custom Dummy driver + config ARM_SCPI_PROTOCOL tristate "ARM System Control and Power Interface (SCPI) Message Protocol" depends on ARM || ARM64 || COMPILE_TEST diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile index 0a03b7432497..361ede03cdb5 100644 --- a/drivers/firmware/arm_scmi/Makefile +++ b/drivers/firmware/arm_scmi/Makefile @@ -12,3 +12,5 @@ obj-$(CONFIG_ARM_SCMI_PROTOCOL_CUSTOM) += scmi_custom.o obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-module.o obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o + +obj-$(CONFIG_ARM_SCMI_CUSTOM_DUMMY) += scmi_custom_dummy.o diff --git a/drivers/firmware/arm_scmi/scmi_custom_dummy.c b/drivers/firmware/arm_scmi/scmi_custom_dummy.c new file mode 100644 index 000000000000..28fd3595a690 --- /dev/null +++ b/drivers/firmware/arm_scmi/scmi_custom_dummy.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * + * Copyright (C) 2018-2020 ARM Ltd. + */ + +#include +#include +#include +#include +#include + +static const struct scmi_dummy_ops *dummy_ops; + +static int dummy_custom_perf_cb(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct scmi_perf_level_report *er = data; + + pr_info("%s()::%d - EVENT:[%ld] - TS:%lld DOMAIN_ID:%d AGENT_ID:%d LEVEL:%d\n", + __func__, __LINE__, event, er->timestamp, er->domain_id, + er->agent_id, er->performance_level); + + return NOTIFY_OK; +} + +static struct notifier_block dummy_custom_perf_nb = { + .notifier_call = dummy_custom_perf_cb, + .priority = 10, +}; + +static int custom_dummy_scream_cb(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct scmi_dummy_scream_report *er = data; + + pr_info("%s()::%d - EVENT:[%ld] - TS:%lld DOMAIN_ID:%d AGENT_ID:%d LEVEL:%d\n", + __func__, __LINE__, event, er->timestamp, er->domain_id, + er->agent_id, er->scream); + + return NOTIFY_OK; +} + +static struct notifier_block custom_dummy_nb = { + .notifier_call = custom_dummy_scream_cb, + .priority = 10, +}; + +static int scmi_dummy_probe(struct scmi_device *sdev) +{ + int num_domains; + struct device *dev = &sdev->dev; + const struct scmi_handle *handle = sdev->handle; + u32 src_id; + + if (!handle) + return -ENODEV; + + dummy_ops = handle->get_ops(handle, SCMI_PROTOCOL_CUSTOM_DUMMY); + if (IS_ERR(dummy_ops)) + return PTR_ERR(dummy_ops); + + num_domains = dummy_ops->num_domains_get(handle); + if (num_domains < 0) { + dev_err(dev, "number of domains not found\n"); + return num_domains; + } + + pr_info("Registering notify_callback as CUSTOM_DUMMY !!\n"); + + src_id = 0x02; + handle->notify_ops->register_event_notifier(handle, + SCMI_PROTOCOL_CUSTOM_DUMMY, + SCMI_EVENT_DUMMY_SCREAM, + &src_id, &custom_dummy_nb); + + src_id = 0x01; + handle->notify_ops->register_event_notifier(handle, + SCMI_PROTOCOL_PERF, + SCMI_EVENT_PERFORMANCE_LEVEL_CHANGED, + &src_id, + &dummy_custom_perf_nb); + + return 0; +} + +static void scmi_dummy_remove(struct scmi_device *sdev) +{ + const struct scmi_handle *handle = sdev->handle; + u32 src_id; + + src_id = 0x02; + handle->notify_ops->unregister_event_notifier(handle, + SCMI_PROTOCOL_CUSTOM_DUMMY, + SCMI_EVENT_DUMMY_SCREAM, + &src_id, &custom_dummy_nb); + + src_id = 0x01; + handle->notify_ops->unregister_event_notifier(handle, + SCMI_PROTOCOL_PERF, + SCMI_EVENT_PERFORMANCE_LEVEL_CHANGED, + &src_id, + &dummy_custom_perf_nb); + + handle->put_ops(handle, SCMI_PROTOCOL_CUSTOM_DUMMY); + + return; +} + +static const struct scmi_device_id scmi_id_table[] = { + { SCMI_PROTOCOL_CUSTOM_DUMMY, "custom_dummy" }, + { }, +}; +MODULE_DEVICE_TABLE(scmi, scmi_id_table); + +static struct scmi_driver scmi_custom_dummy_driver = { + .name = "scmi-custom-dummy", + .probe = scmi_dummy_probe, + .remove = scmi_dummy_remove, + .id_table = scmi_id_table, +}; +module_scmi_driver(scmi_custom_dummy_driver); + +MODULE_AUTHOR("DummyMaster"); +MODULE_DESCRIPTION("ARM SCMI Custom Dummy driver"); +MODULE_LICENSE("GPL v2"); From patchwork Wed Oct 14 15:05:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11837855 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 BC339921 for ; Wed, 14 Oct 2020 15:09:46 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (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 58D4321582 for ; Wed, 14 Oct 2020 15:09: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="uGLXNI/v" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 58D4321582 Authentication-Results: mail.kernel.org; dmarc=fail (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=merlin.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=/1Dih57lekncRKq/MhWy0o416+rx8mTMfOyaJZ1U+PU=; b=uGLXNI/v+JvG1KDSqhlbTUq+KZ tWpZSfvj3hI6VYr2ulyDcdJ5LPVBI2KOqFseERVr6jCbI5aWg8Dr/ONvq8hK8EKMVDWsPTKGwMZBa FLAK4iYsPgddroiR28uq4ku+cH2SzBbSbUVCfb80zNiFD6G8GDhRyrazrI9PWloerF5SC8MoXGadC X6C4ictBNPcUFGCmzijsRKO6q4Oe14fAvq4EalWUqOr5VcAoXKuffJbvckWWJr9jfvZesaVH9lxDr pHoHkyIVxrGcNrOzoI15m+g9Z+PLYg1d1Md9wBTJf+hnVIy5io8mDET1M8ddz1bFms9z/TBO/OFOg cgIv3L8A==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kSiNr-0001hc-Kc; Wed, 14 Oct 2020 15:08:07 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kSiMy-0001Nv-Uq for linux-arm-kernel@lists.infradead.org; Wed, 14 Oct 2020 15:07:15 +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 868BA1424; Wed, 14 Oct 2020 08:07:12 -0700 (PDT) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id CEA493F71F; Wed, 14 Oct 2020 08:07:10 -0700 (PDT) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH 10/11] [DEBUG] firmware: arm_scmi: add custom_dummy SCMI devname Date: Wed, 14 Oct 2020 16:05:44 +0100 Message-Id: <20201014150545.44807-11-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201014150545.44807-1-cristian.marussi@arm.com> References: <20201014150545.44807-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201014_110713_090699_319C46B5 X-CRM114-Status: GOOD ( 11.56 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.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: f.fainelli@gmail.com, vincent.guittot@linaro.org, sudeep.holla@arm.com, thara.gopinath@linaro.org, cristian.marussi@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, souvik.chakravarty@arm.com, etienne.carriere@linaro.org, lukasz.luba@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 custom_dummy SCMI devname. Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/driver.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 55df134c2338..5c39a738866a 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -993,6 +993,7 @@ static struct scmi_prot_devnames devnames[] = { { SCMI_PROTOCOL_CLOCK, { "clocks" },}, { SCMI_PROTOCOL_SENSOR, { "hwmon" },}, { SCMI_PROTOCOL_RESET, { "reset" },}, + { SCMI_PROTOCOL_CUSTOM_DUMMY, { "custom_dummy" },}, }; static inline void From patchwork Wed Oct 14 15:05:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 11837847 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 C61F861C for ; Wed, 14 Oct 2020 15:08:23 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (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 7A09E22227 for ; Wed, 14 Oct 2020 15:08:23 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="YW0hqTka" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7A09E22227 Authentication-Results: mail.kernel.org; dmarc=fail (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=merlin.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=cDhv8Pguj/3wDMMsCeLYT+8/plsddf4NZ63NaErFxBQ=; b=YW0hqTka8Hk76KVAD71gIrO8XI bSepQSBWdaFSe5UbWlRwQRU4NZB35K5tc1B2rJ05Nk4LJP9g5iZWOJ84VfsHuH8EDTy1YBBLVVdE9 9UtUEVOoPZrjkbftKhSEwT5tVjgANUvAi5Q9imBEPr+k6ogy3pYKFpNarFL2Cw0QqPMzQfUDy/BZs wwtiUTNTB+Sg6oDP1qCHDIgiuFsHf/retTt3mQcpRgBvWfkwxMORGpmt4GTxaFAhmOtwIloLSLj4e RlESZM5nQBUiF1t+p+mg4JzcxlKUD8P6jvd85jkshn5YH3yd5ovLB7t9poF2nc6aTAlvinBMON3A/ /2QaCWGw==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kSiNu-0001ix-5y; Wed, 14 Oct 2020 15:08:10 +0000 Received: from foss.arm.com ([217.140.110.172]) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kSiN0-0001Og-US for linux-arm-kernel@lists.infradead.org; Wed, 14 Oct 2020 15:07:17 +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 629671435; Wed, 14 Oct 2020 08:07:14 -0700 (PDT) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id BC94B3F71F; Wed, 14 Oct 2020 08:07:12 -0700 (PDT) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH 11/11] [DEBUG][HACK] firmware: arm_scmi: force implemented protocol 0x99 Date: Wed, 14 Oct 2020 16:05:45 +0100 Message-Id: <20201014150545.44807-12-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201014150545.44807-1-cristian.marussi@arm.com> References: <20201014150545.44807-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201014_110715_089114_CD46DEC7 X-CRM114-Status: GOOD ( 10.77 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.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: f.fainelli@gmail.com, vincent.guittot@linaro.org, sudeep.holla@arm.com, thara.gopinath@linaro.org, cristian.marussi@arm.com, james.quinlan@broadcom.com, Jonathan.Cameron@Huawei.com, souvik.chakravarty@arm.com, etienne.carriere@linaro.org, lukasz.luba@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 Force custom protocol 0x99 as implemented for testing purposes. Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/base.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c index 8d7214fd2187..b0036111e287 100644 --- a/drivers/firmware/arm_scmi/base.c +++ b/drivers/firmware/arm_scmi/base.c @@ -356,6 +356,8 @@ static int scmi_base_protocol_init(const struct scmi_handle *h, scmi_base_vendor_id_get(handle, true); scmi_base_implementation_version_get(handle); scmi_base_implementation_list_get(handle, prot_imp); + handle->version->num_protocols++; + prot_imp[handle->version->num_protocols] = SCMI_PROTOCOL_CUSTOM_DUMMY; scmi_setup_protocol_implemented(handle, prot_imp); dev_info(dev, "SCMI Protocol v%d.%d '%s:%s' Firmware version 0x%x\n",