From patchwork Wed Jan 6 20:15:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Marussi X-Patchwork-Id: 12002161 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8D17DC43381 for ; Wed, 6 Jan 2021 20:19:51 +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 46BEC22B40 for ; Wed, 6 Jan 2021 20:19:51 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 46BEC22B40 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+linux-arm-kernel=archiver.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=k002fn/XM4BsA9BEaxJNTy9wpiWNMOPegpm5dyCs3VU=; b=M14vCwbOORe2w5cmLj+YTxAxGL bII+cA25LWh+hDbSOucu88f8bVOgbXKt8XuPOQKRFaiWe0M8ZvzYjfEFdsT05g3hS3uAJ8c6KZTuL DWvtn8sigQkBmGj+V9WZz27kT21Kuu5gHkek1C6IgRosIzbQiw646Ftas16ggcWzEu9AmHYVcnxAP 5SAov2v4hdJbtFKIQM40WJQVnROYuJFMfSqA+3/vcuFwxWRUK+GYjuo6PpaabL5FhTsOQ3VbZE/a8 Tu/dbhxzWpUeq3b8qT1u7HpqAFjF5JUjfe8L+xX2TFwJmOUrGgPOt0SOB2u9Oxe0nbXyLlwgX5vG1 59ENfi0g==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kxFFT-0004DC-24; Wed, 06 Jan 2021 20:17:39 +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 1kxFEw-00042a-O0 for linux-arm-kernel@lists.infradead.org; Wed, 06 Jan 2021 20:17: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 A6D57139F; Wed, 6 Jan 2021 12:17:05 -0800 (PST) Received: from e120937-lin.home (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 8FD213F719; Wed, 6 Jan 2021 12:17:03 -0800 (PST) From: Cristian Marussi To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH v4 06/37] firmware: arm_scmi: introduce new devres notification ops Date: Wed, 6 Jan 2021 20:15:39 +0000 Message-Id: <20210106201610.26538-7-cristian.marussi@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210106201610.26538-1-cristian.marussi@arm.com> References: <20210106201610.26538-1-cristian.marussi@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210106_151707_226909_49A7655A X-CRM114-Status: GOOD ( 21.39 ) 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+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Expose to the SCMI drivers a new alternative devres managed notifications API based on protocol handles. All drivers still keep using the old API, no functional change. Signed-off-by: Cristian Marussi --- drivers/firmware/arm_scmi/notify.c | 123 +++++++++++++++++++++++++++++ include/linux/scmi_protocol.h | 15 +++- 2 files changed, 137 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c index cdaf0f962d84..70e8eb4e33c6 100644 --- a/drivers/firmware/arm_scmi/notify.c +++ b/drivers/firmware/arm_scmi/notify.c @@ -1408,6 +1408,127 @@ static int scmi_unregister_notifier(const struct scmi_handle *handle, return 0; } +struct scmi_notifier_devres { + const struct scmi_handle *handle; + u8 proto_id; + u8 evt_id; + u32 __src_id; + u32 *src_id; + struct notifier_block *nb; +}; + +static void scmi_devm_release_notifier(struct device *dev, void *res) +{ + struct scmi_notifier_devres *dres = res; + + scmi_unregister_notifier(dres->handle, dres->proto_id, dres->evt_id, + dres->src_id, dres->nb); +} + +/** + * scmi_devm_register_notifier() - Managed registration of a notifier_block + * for an event + * @sdev: A reference to an scmi_device whose embedded struct device is to + * be used for devres accounting. + * @proto_id: Protocol ID + * @evt_id: Event ID + * @src_id: Source ID, when NULL register for events coming form ALL possible + * sources + * @nb: A standard notifier block to register for the specified event + * + * Generic devres managed helper to register a notifier_block against a + * protocol event. + */ +static int scmi_devm_register_notifier(struct scmi_device *sdev, + u8 proto_id, u8 evt_id, u32 *src_id, + struct notifier_block *nb) +{ + int ret; + struct scmi_notifier_devres *dres; + + dres = devres_alloc(scmi_devm_release_notifier, + sizeof(*dres), GFP_KERNEL); + if (!dres) + return -ENOMEM; + + ret = scmi_register_notifier(sdev->handle, proto_id, + evt_id, src_id, nb); + if (ret) { + devres_free(dres); + return ret; + } + + dres->handle = sdev->handle; + dres->proto_id = proto_id; + dres->evt_id = evt_id; + dres->nb = nb; + if (src_id) { + dres->__src_id = *src_id; + dres->src_id = &dres->__src_id; + } else { + dres->src_id = NULL; + } + devres_add(&sdev->dev, dres); + + return ret; +} + +static int scmi_devm_notifier_match(struct device *dev, void *res, void *data) +{ + struct scmi_notifier_devres *dres = res; + struct scmi_notifier_devres *xres = data; + + if (WARN_ON(!dres || !xres)) + return 0; + + return dres->proto_id == xres->proto_id && + dres->evt_id == xres->evt_id && + dres->nb == xres->nb && + ((!dres->src_id && !xres->src_id) || + (dres->src_id && xres->src_id && + dres->__src_id == xres->__src_id)); +} + +/** + * scmi_devm_unregister_notifier() - Managed un-registration of a + * notifier_block for an event + * @sdev: A reference to an scmi_device whose embedded struct device is to + * be used for devres accounting. + * @proto_id: Protocol ID + * @evt_id: Event ID + * @src_id: Source ID, when NULL register for events coming form ALL possible + * sources + * @nb: A standard notifier block to register for the specified event + * + * Generic devres managed helper to explicitly un-register a notifier_block + * against a protocol event, which was previously registered using the above + * @scmi_devm_register_notifier. + */ +static int scmi_devm_unregister_notifier(struct scmi_device *sdev, + u8 proto_id, u8 evt_id, u32 *src_id, + struct notifier_block *nb) +{ + int ret; + struct scmi_notifier_devres dres; + + dres.handle = sdev->handle; + dres.proto_id = proto_id; + dres.evt_id = evt_id; + if (src_id) { + dres.__src_id = *src_id; + dres.src_id = &dres.__src_id; + } else { + dres.src_id = NULL; + } + + ret = devres_release(&sdev->dev, scmi_devm_release_notifier, + scmi_devm_notifier_match, &dres); + + WARN_ON(ret); + + return ret; +} + /** * scmi_protocols_late_init() - Worker for late initialization * @work: The work item to use associated to the proper SCMI instance @@ -1465,6 +1586,8 @@ static void scmi_protocols_late_init(struct work_struct *work) * directly from an scmi_driver to register its own notifiers. */ static const struct scmi_notify_ops notify_ops = { + .devm_register_event_notifier = scmi_devm_register_notifier, + .devm_unregister_event_notifier = scmi_devm_unregister_notifier, .register_event_notifier = scmi_register_notifier, .unregister_event_notifier = scmi_unregister_notifier, }; diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index 8a2bb723602f..88757639f790 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -544,6 +544,10 @@ struct scmi_voltage_ops { /** * struct scmi_notify_ops - represents notifications' operations provided by * SCMI core + * @devm_register_event_notifier: Managed registration of a notifier_block for + * the requested event + * @devm_unregister_event_notifier: Managed unregistration of a notifier_block + * for the requested event * @register_event_notifier: Register a notifier_block for the requested event * @unregister_event_notifier: Unregister a notifier_block for the requested * event @@ -553,7 +557,9 @@ struct scmi_voltage_ops { * tuple: (proto_id, evt_id, src_id) using the provided register/unregister * interface where: * - * @handle: The handle identifying the platform instance to use + * @sdev: The scmi_device to use when calling the devres managed ops devm_ + * @handle: The handle identifying the platform instance to use, when not + * calling the managed ops devm_ * @proto_id: The protocol ID as in SCMI Specification * @evt_id: The message ID of the desired event as in SCMI Specification * @src_id: A pointer to the desired source ID if different sources are @@ -576,6 +582,13 @@ struct scmi_voltage_ops { * @report: A custom struct describing the specific event delivered */ struct scmi_notify_ops { + int (*devm_register_event_notifier)(struct scmi_device *sdev, + u8 proto_id, u8 evt_id, u32 *src_id, + struct notifier_block *nb); + int (*devm_unregister_event_notifier)(struct scmi_device *sdev, + u8 proto_id, u8 evt_id, + u32 *src_id, + struct notifier_block *nb); int (*register_event_notifier)(const struct scmi_handle *handle, u8 proto_id, u8 evt_id, u32 *src_id, struct notifier_block *nb);