From patchwork Tue May 11 00:20:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Hilber X-Patchwork-Id: 434399 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=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7F3D7C433B4 for ; Tue, 11 May 2021 00:28:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5032F61613 for ; Tue, 11 May 2021 00:28:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231649AbhEKA36 (ORCPT ); Mon, 10 May 2021 20:29:58 -0400 Received: from mx1.opensynergy.com ([217.66.60.4]:14836 "EHLO mx1.opensynergy.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231425AbhEKA3t (ORCPT ); Mon, 10 May 2021 20:29:49 -0400 Received: from SR-MAILGATE-02.opensynergy.com (localhost.localdomain [127.0.0.1]) by mx1.opensynergy.com (Proxmox) with ESMTP id 962D8A1987; Tue, 11 May 2021 02:22:03 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=opensynergy.com; h=cc:cc:content-transfer-encoding:content-type:content-type :date:from:from:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=srmailgate02; bh=ZmQx0CHn1ZF5 cPFnLZkXuV6S6R2qGPhY3pMc8jECLR4=; b=il1zd/GZusW0+LGf64dGfIzZfK2X 6rtXy4NzRDPp/xJ/H9LD/u3lb+mEbrDfkrq0otBFs0FmD7doJa6WYAI8zvzKLuI6 TzSblCZ08WtYp1Yo8aI/8YXf84U0Ocepsutiw2ruyb7cGCENsKkQc9wVGLr5OA1+ ygcmRTnfhRIjeRYjGVwoHlKKx3e7W/2qiyQpDfMhXvGq2mkREcmQ9FJNu74y3DED bGSdsGny+e/xIUR5Rh1dopIcNptVkHBpsVFOrkJ57mhvGdg2c4j/Y8W/YHsajAm3 6xbtDEwy46drTlR/JpejC4fPb2HuaBZyFZDnAlBkyykGJq8BOjZ7xSJyTw== From: Peter Hilber To: , CC: Igor Skalkin , Peter Hilber , Rob Herring , , , , , , , , Vasyl Vavrychuk , Andriy Tryshnivskyy , Cristian Marussi , Mark Rutland , Lorenzo Pieralisi , Jassi Brar Subject: [RFC PATCH v3 01/12] firmware: arm_scmi, smccc, mailbox: Make shmem based transports optional Date: Tue, 11 May 2021 02:20:29 +0200 Message-ID: <20210511002040.802226-2-peter.hilber@opensynergy.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210511002040.802226-1-peter.hilber@opensynergy.com> References: <20210511002040.802226-1-peter.hilber@opensynergy.com> MIME-Version: 1.0 X-ClientProxiedBy: SR-MAIL-01.open-synergy.com (10.26.10.21) To SR-MAIL-02.open-synergy.com (10.26.10.22) Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Igor Skalkin Upon adding the virtio transport in this patch series, SCMI will also work without shared memory based transports. Also, the mailbox transport may not be needed if the smc transport is used. - Compile shmem.c only if a shmem based transport is available. - Remove hard dependency of SCMI on mailbox. Signed-off-by: Igor Skalkin [ Peter: Adapted patch for submission to upstream. ] Co-developed-by: Peter Hilber Signed-off-by: Peter Hilber --- drivers/firmware/Kconfig | 8 +++++++- drivers/firmware/arm_scmi/Makefile | 2 +- drivers/firmware/arm_scmi/common.h | 2 ++ drivers/firmware/arm_scmi/driver.c | 2 ++ drivers/firmware/smccc/Kconfig | 1 + drivers/mailbox/Kconfig | 1 + 6 files changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index db0ea2d2d75a..80ff49dadf35 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -9,7 +9,7 @@ menu "Firmware Drivers" config ARM_SCMI_PROTOCOL tristate "ARM System Control and Management Interface (SCMI) Message Protocol" depends on ARM || ARM64 || COMPILE_TEST - depends on MAILBOX + depends on ARM_SCMI_HAVE_SHMEM help ARM System Control and Management Interface (SCMI) protocol is a set of operating system-independent software interfaces that are @@ -27,6 +27,12 @@ config ARM_SCMI_PROTOCOL This protocol library provides interface for all the client drivers making use of the features offered by the SCMI. +config ARM_SCMI_HAVE_SHMEM + bool + help + This declares whether a shared memory based transport for SCMI is + available. + 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 6a2ef63306d6..5a2d4c32e0ae 100644 --- a/drivers/firmware/arm_scmi/Makefile +++ b/drivers/firmware/arm_scmi/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only scmi-bus-y = bus.o scmi-driver-y = driver.o notify.o -scmi-transport-y = shmem.o +scmi-transport-$(CONFIG_ARM_SCMI_HAVE_SHMEM) = shmem.o scmi-transport-$(CONFIG_MAILBOX) += mailbox.o 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 voltage.o diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 228bf4a71d23..94dcfb8c0176 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -330,7 +330,9 @@ struct scmi_desc { int max_msg_size; }; +#ifdef CONFIG_MAILBOX extern const struct scmi_desc scmi_mailbox_desc; +#endif #ifdef CONFIG_HAVE_ARM_SMCCC extern const struct scmi_desc scmi_smc_desc; #endif diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 66eb3f0e5daf..41d80bbaa9a2 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -1567,7 +1567,9 @@ ATTRIBUTE_GROUPS(versions); /* Each compatible listed below must have descriptor associated with it */ static const struct of_device_id scmi_of_match[] = { +#ifdef CONFIG_MAILBOX { .compatible = "arm,scmi", .data = &scmi_mailbox_desc }, +#endif #ifdef CONFIG_HAVE_ARM_SMCCC_DISCOVERY { .compatible = "arm,scmi-smc", .data = &scmi_smc_desc}, #endif diff --git a/drivers/firmware/smccc/Kconfig b/drivers/firmware/smccc/Kconfig index 15e7466179a6..69c4d6cabf62 100644 --- a/drivers/firmware/smccc/Kconfig +++ b/drivers/firmware/smccc/Kconfig @@ -9,6 +9,7 @@ config HAVE_ARM_SMCCC_DISCOVERY bool depends on ARM_PSCI_FW default y + select ARM_SCMI_HAVE_SHMEM help SMCCC v1.0 lacked discoverability and hence PSCI v1.0 was updated to add SMCCC discovery mechanism though the PSCI firmware diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 68de2c6af727..fc02c38c0739 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only menuconfig MAILBOX bool "Mailbox Hardware Support" + select ARM_SCMI_HAVE_SHMEM help Mailbox is a framework to control hardware communication between on-chip processors through queued messages and interrupt driven From patchwork Tue May 11 00:20:30 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Hilber X-Patchwork-Id: 434403 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=-16.0 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, UNWANTED_LANGUAGE_BODY,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9B22DC433B4 for ; Tue, 11 May 2021 00:28:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4B12861613 for ; Tue, 11 May 2021 00:28:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231193AbhEKA3p (ORCPT ); Mon, 10 May 2021 20:29:45 -0400 Received: from mx1.opensynergy.com ([217.66.60.4]:12383 "EHLO mx1.opensynergy.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230503AbhEKA3o (ORCPT ); Mon, 10 May 2021 20:29:44 -0400 X-Greylist: delayed 394 seconds by postgrey-1.27 at vger.kernel.org; Mon, 10 May 2021 20:29:43 EDT Received: from SR-MAILGATE-02.opensynergy.com (localhost.localdomain [127.0.0.1]) by mx1.opensynergy.com (Proxmox) with ESMTP id 4B3C3A1A12; Tue, 11 May 2021 02:22:04 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=opensynergy.com; h=cc:cc:content-transfer-encoding:content-type:content-type :date:from:from:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=srmailgate02; bh=OU+HtaTs8Fvo JVnDadVJ79nNHdyp+spOITIiOi6q/EY=; b=Q6e3d650yUpUKNqe1tItVEO+y1Of mkEptEEXBi3JmUTqq0hYd9Wl/L8iwt4cWn09CUoEQhd9oo//HYwNbmw8wDZFEP+F PST0J/epi8V0j545ALWeXD4UMPHnErPKW4cgYxlER8yYLbR1ZVaX+O75va+OWujO HvdNHIkHezDdZ7cFH8xzpJdbbcHclCVZPXvC1R79MKd7B31huAGQ2hMCQHFGOk7f 3vEGl260cGGfZnKFMgNdQw3YcPLnmZ66VgpHESL7Am/MgLPaiwFIJhvAL7BY2EKc SKchiSGSYuMTzfrDbeBJIJoE1CkZkjxbpl9+gW6M0yp6ypxKDh1iMvHJ2A== From: Peter Hilber To: , CC: Cristian Marussi , Peter Hilber , Rob Herring , , , , , , , , , Vasyl Vavrychuk , Andriy Tryshnivskyy Subject: [RFC PATCH v3 02/12] firmware: arm_scmi: Add transport init/deinit Date: Tue, 11 May 2021 02:20:30 +0200 Message-ID: <20210511002040.802226-3-peter.hilber@opensynergy.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210511002040.802226-1-peter.hilber@opensynergy.com> References: <20210511002040.802226-1-peter.hilber@opensynergy.com> MIME-Version: 1.0 X-ClientProxiedBy: SR-MAIL-01.open-synergy.com (10.26.10.21) To SR-MAIL-02.open-synergy.com (10.26.10.22) Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Cristian Marussi Signed-off-by: Cristian Marussi [ Peter: Adapted RFC patch by Cristian for submission to upstream. ] Signed-off-by: Peter Hilber --- drivers/firmware/arm_scmi/common.h | 2 ++ drivers/firmware/arm_scmi/driver.c | 45 ++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 94dcfb8c0176..961a3c63cc42 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -324,6 +324,8 @@ struct scmi_device *scmi_child_dev_find(struct device *parent, * @max_msg_size: Maximum size of data per message that can be handled. */ struct scmi_desc { + int (*init)(void); + void (*exit)(void); const struct scmi_transport_ops *ops; int max_rx_timeout_ms; int max_msg; diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 41d80bbaa9a2..471c5de827c1 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -1588,10 +1588,53 @@ static struct platform_driver scmi_driver = { .remove = scmi_remove, }; +static inline int __scmi_transports_setup(bool init) +{ + int ret = 0; + const struct of_device_id *trans; + + for (trans = scmi_of_match; trans->data; trans++) { + const struct scmi_desc *tdesc = trans->data; + + if ((init && !tdesc->init) || !tdesc->exit) + continue; + pr_info("SCMI %sInitializing %s transport\n", init ? "" : "De-", + trans->compatible); + if (init) + ret = tdesc->init(); + else + tdesc->exit(); + + if (ret) { + pr_err("SCMI transport %s FAILED initialization!\n", + trans->compatible); + break; + } + } + + return ret; +} + +static int __init scmi_transports_init(void) +{ + return __scmi_transports_setup(true); +} + +static void __exit scmi_transports_exit(void) +{ + __scmi_transports_setup(false); +} + static int __init scmi_driver_init(void) { + int ret; + scmi_bus_init(); + ret = scmi_transports_init(); + if (ret) + return ret; + scmi_base_register(); scmi_clock_register(); @@ -1618,6 +1661,8 @@ static void __exit scmi_driver_exit(void) scmi_voltage_unregister(); scmi_system_unregister(); + scmi_transports_exit(); + scmi_bus_exit(); platform_driver_unregister(&scmi_driver); From patchwork Tue May 11 00:20:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Hilber X-Patchwork-Id: 434400 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=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1C35CC433B4 for ; Tue, 11 May 2021 00:28:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E04F761613 for ; Tue, 11 May 2021 00:28:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231551AbhEKA3y (ORCPT ); Mon, 10 May 2021 20:29:54 -0400 Received: from mx1.opensynergy.com ([217.66.60.4]:8128 "EHLO mx1.opensynergy.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231416AbhEKA3t (ORCPT ); Mon, 10 May 2021 20:29:49 -0400 Received: from SR-MAILGATE-02.opensynergy.com (localhost.localdomain [127.0.0.1]) by mx1.opensynergy.com (Proxmox) with ESMTP id 7D13CA1A2E; Tue, 11 May 2021 02:22:06 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=opensynergy.com; h=cc:cc:content-transfer-encoding:content-type:content-type :date:from:from:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=srmailgate02; bh=6+VlSkKWGdjk DM6nZTn7Ha5NxKkKwBbIL6DCLdewkbA=; b=CGnQklXHC54GKgHiTz1MnYznchZN K0SvNZczQ/nM6pQopfMiFXgQ1Y5Bz0F1Piarn8SQ6qSXSHWJmqATT06yIQSNRLC3 Mlc8FLjDLl4uToDbeqbSQ3fIF/2RE8zT93ferkKSKP3awqndteNHn+UFhwjhoTJX 73x+yhxH6cgqmgusSRcdlaJL+SdKItlvIMmT54dtJedOH/zwenv8eZnjAESqXSlL FVsCR4Kh4hF8OtbqXUYIVm0+PCrYcyZx0ka8A7wxFGNsYVadRiObSsYAPJEzc3aV 81lzp8hXK0xYmnRCEDkg6ktg0+mcbIJIbnv+jUPn0y5CEyhCq/aBmVlLig== From: Peter Hilber To: , CC: Peter Hilber , Rob Herring , , , , , , , , , Vasyl Vavrychuk , Andriy Tryshnivskyy , Cristian Marussi Subject: [RFC PATCH v3 05/12] firmware: arm_scmi: Add per-device transport private info Date: Tue, 11 May 2021 02:20:33 +0200 Message-ID: <20210511002040.802226-6-peter.hilber@opensynergy.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210511002040.802226-1-peter.hilber@opensynergy.com> References: <20210511002040.802226-1-peter.hilber@opensynergy.com> MIME-Version: 1.0 X-ClientProxiedBy: SR-MAIL-01.open-synergy.com (10.26.10.21) To SR-MAIL-02.open-synergy.com (10.26.10.22) Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org The scmi-virtio transport will link a supplier device to the arm-scmi device in the link_supplier() op. The transport should then save a pointer to the linked device. To enable this, add a transport private info to the scmi_info. (The scmi_info is already reachable through the arm-scmi device driver_data.) Signed-off-by: Peter Hilber --- drivers/firmware/arm_scmi/common.h | 2 ++ drivers/firmware/arm_scmi/driver.c | 35 ++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index d60e3c26821d..61b22cdeaeeb 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -346,6 +346,8 @@ extern const struct scmi_desc scmi_mailbox_desc; extern const struct scmi_desc scmi_smc_desc; #endif +int scmi_set_transport_info(struct device *dev, void *transport_info); +void *scmi_get_transport_info(struct device *dev); void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr); void scmi_free_channel(struct scmi_chan_info *cinfo, struct idr *idr, int id); diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index df526ff37c6d..581b6c9b3781 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -127,6 +127,7 @@ struct scmi_protocol_instance { * @active_protocols: IDR storing device_nodes for protocols actually defined * in the DT and confirmed as implemented by fw. * @notify_priv: Pointer to private data structure specific to notifications. + * @transport_info: Transport private info * @node: List head * @users: Number of users of this instance */ @@ -145,6 +146,7 @@ struct scmi_info { u8 *protocols_imp; struct idr active_protocols; void *notify_priv; + void *transport_info; struct list_head node; int users; }; @@ -382,6 +384,39 @@ void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr) } } +/** + * scmi_set_transport_info() - Set transport private info + * + * @dev: SCMI instance device + * @transport_info: transport private info + * + * Return: 0 on success, otherwise error. + */ +int scmi_set_transport_info(struct device *dev, void *transport_info) +{ + struct scmi_info *info = dev_get_drvdata(dev); + + if (!info) + return -EBADR; + + info->transport_info = transport_info; + return 0; +} + +/** + * scmi_get_transport_info() - Get transport private info + * + * @dev: SCMI instance device + * + * Return: transport private info on success, otherwise NULL. + */ +void *scmi_get_transport_info(struct device *dev) +{ + struct scmi_info *info = dev_get_drvdata(dev); + + return info ? info->transport_info : NULL; +} + /** * xfer_put() - Release a transmit message * From patchwork Tue May 11 00:20:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Hilber X-Patchwork-Id: 434397 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=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DF7DFC43600 for ; Tue, 11 May 2021 00:28:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B481A610CA for ; Tue, 11 May 2021 00:28:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231651AbhEKA37 (ORCPT ); Mon, 10 May 2021 20:29:59 -0400 Received: from mx1.opensynergy.com ([217.66.60.4]:31975 "EHLO mx1.opensynergy.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231422AbhEKA3u (ORCPT ); Mon, 10 May 2021 20:29:50 -0400 Received: from SR-MAILGATE-02.opensynergy.com (localhost.localdomain [127.0.0.1]) by mx1.opensynergy.com (Proxmox) with ESMTP id 1B765A1A30; Tue, 11 May 2021 02:22:07 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=opensynergy.com; h=cc:cc:content-transfer-encoding:content-type:content-type :date:from:from:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=srmailgate02; bh=uVXQj8vtCYso WfIdT2YmI6MruqMQhZ51sMrsMngt+4c=; b=bub2NUPQ/1YkHW/fBbb4rG6AQdkz 53zguMOjN7F+aEjMXK1IfPIpCrOOb0eNS5MMVhePifFi074BXvPPYN/sAWXRvrmX TdwmYlCc9MAPpVMEB15jf6tLCejtiebPengFdBWMFH0RDhUIiBRM45bOTU7bnupZ z6Slz8DMjiJ1/7jmL7EzPoZtR7vEDYjhQnVY3+7j/yekK7HDF5wXZMGQ718WK9Pb lRTLW3ZWqKv7QkP7ZK0+Up369Rrm3ZV8bZ9CKbe3VcbPy0lGlQrYkzrlppef/5fA SHAOMj5sSelTbNboJRAcJbQIWyHjSDPupXKXtlortgkHOaIVnQWRoQYnXA== From: Peter Hilber To: , CC: Peter Hilber , Rob Herring , , , , , , , , , Vasyl Vavrychuk , Andriy Tryshnivskyy , Cristian Marussi Subject: [RFC PATCH v3 06/12] firmware: arm_scmi: Add is_scmi_protocol_device() Date: Tue, 11 May 2021 02:20:34 +0200 Message-ID: <20210511002040.802226-7-peter.hilber@opensynergy.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210511002040.802226-1-peter.hilber@opensynergy.com> References: <20210511002040.802226-1-peter.hilber@opensynergy.com> MIME-Version: 1.0 X-ClientProxiedBy: SR-MAIL-01.open-synergy.com (10.26.10.21) To SR-MAIL-02.open-synergy.com (10.26.10.22) Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org The scmi-virtio transport driver will need to distinguish SCMI protocol devices from the SCMI instance device in the chan_setup() and chan_free() ops. Add this internal helper to be able to distinguish the two. Signed-off-by: Peter Hilber --- drivers/firmware/arm_scmi/bus.c | 5 +++++ drivers/firmware/arm_scmi/common.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c index 784cf0027da3..06148e972d1a 100644 --- a/drivers/firmware/arm_scmi/bus.c +++ b/drivers/firmware/arm_scmi/bus.c @@ -134,6 +134,11 @@ static struct bus_type scmi_bus_type = { .remove = scmi_dev_remove, }; +bool is_scmi_protocol_device(struct device *dev) +{ + return dev->bus == &scmi_bus_type; +} + int scmi_driver_register(struct scmi_driver *driver, struct module *owner, const char *mod_name) { diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 61b22cdeaeeb..9488c682a51d 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -231,6 +231,8 @@ struct scmi_protocol { const struct scmi_protocol_events *events; }; +bool is_scmi_protocol_device(struct device *dev); + int __init scmi_bus_init(void); void __exit scmi_bus_exit(void); From patchwork Tue May 11 00:20:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Hilber X-Patchwork-Id: 434402 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=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 927E8C43460 for ; Tue, 11 May 2021 00:28:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5FF2D610CA for ; Tue, 11 May 2021 00:28:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231439AbhEKA3r (ORCPT ); Mon, 10 May 2021 20:29:47 -0400 Received: from mx1.opensynergy.com ([217.66.60.4]:26881 "EHLO mx1.opensynergy.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231131AbhEKA3o (ORCPT ); Mon, 10 May 2021 20:29:44 -0400 Received: from SR-MAILGATE-02.opensynergy.com (localhost.localdomain [127.0.0.1]) by mx1.opensynergy.com (Proxmox) with ESMTP id 3D911A1A32; Tue, 11 May 2021 02:22:08 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=opensynergy.com; h=cc:cc:content-transfer-encoding:content-type:content-type :date:from:from:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=srmailgate02; bh=/5Dxcbib2uhu l8GgPx/VJRtYLOF11009NaDVvtRbKkg=; b=ZeN6OTiYGFHRcbQZmlEyWwXZybUo J3X0++xambBLe+GJ+VSQ8qmpUE7x97am3+9Gh3bHPPHXpJPVWpB7Rl9EEuGnchcY MLPHkrdVnCNDoP55fS2pZw9BT0sDMglxLPjgZNu+tI0svX9bOxyG/p2bprfHjTV/ Xr5phJJhWRymwbiT23Fai5395Px8DRZRP0YrjxNIw70q0kag6zYZIPrmDHJc339s 4u1xpa73CjqfFF15zz4rr0SKh77wKXhZp2S3TuNUw5mHf7Qf86IiQULED0kpDHwW KNH6O05SlpEyCy7d+MEk24pIOPPSepzdF3cC1tTRJC+ZmtrjL20SJFylAg== From: Peter Hilber To: , CC: Peter Hilber , Rob Herring , , , , , , , , , Vasyl Vavrychuk , Andriy Tryshnivskyy , Cristian Marussi Subject: [RFC PATCH v3 07/12] firmware: arm_scmi: Add msg_handle to some transport ops Date: Tue, 11 May 2021 02:20:35 +0200 Message-ID: <20210511002040.802226-8-peter.hilber@opensynergy.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210511002040.802226-1-peter.hilber@opensynergy.com> References: <20210511002040.802226-1-peter.hilber@opensynergy.com> MIME-Version: 1.0 X-ClientProxiedBy: SR-MAIL-01.open-synergy.com (10.26.10.21) To SR-MAIL-02.open-synergy.com (10.26.10.22) Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org The upcoming virtio transport may xfer several SCMI messages in parallel on a channel. But the transport ops which fetch messages lack information through which a transport can determine which of several messages the core intends to address. The virtio transport should not rely on the current implementation details of the core to deduce the message. Disambiguate this by having the transport pass an opaque message handle to scmi_rx_callback(), which the transport will then use in the message fetching transport ops to identify which message to address. Do not address how to handle the polling mechanism for now. The existing transports can just ignore the message handle. Signed-off-by: Peter Hilber --- drivers/firmware/arm_scmi/common.h | 8 ++++---- drivers/firmware/arm_scmi/driver.c | 20 +++++++++++--------- drivers/firmware/arm_scmi/mailbox.c | 7 ++++--- drivers/firmware/arm_scmi/smc.c | 5 +++-- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 9488c682a51d..5ab2ea0f7db2 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -310,9 +310,9 @@ struct scmi_transport_ops { struct scmi_xfer *xfer); void (*mark_txdone)(struct scmi_chan_info *cinfo, int ret); void (*fetch_response)(struct scmi_chan_info *cinfo, - struct scmi_xfer *xfer); - void (*fetch_notification)(struct scmi_chan_info *cinfo, - size_t max_len, struct scmi_xfer *xfer); + struct scmi_xfer *xfer, void *msg_handle); + void (*fetch_notification)(struct scmi_chan_info *cinfo, size_t max_len, + struct scmi_xfer *xfer, void *msg_handle); void (*clear_channel)(struct scmi_chan_info *cinfo); bool (*poll_done)(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer); }; @@ -350,7 +350,7 @@ extern const struct scmi_desc scmi_smc_desc; int scmi_set_transport_info(struct device *dev, void *transport_info); void *scmi_get_transport_info(struct device *dev); -void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr); +void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr, void *msg_handle); void scmi_free_channel(struct scmi_chan_info *cinfo, struct idr *idr, int id); /* shmem related declarations */ diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 581b6c9b3781..cc27978b4bea 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -272,7 +272,8 @@ __scmi_xfer_put(struct scmi_xfers_info *minfo, struct scmi_xfer *xfer) spin_unlock_irqrestore(&minfo->xfer_lock, flags); } -static void scmi_handle_notification(struct scmi_chan_info *cinfo, u32 msg_hdr) +static void scmi_handle_notification(struct scmi_chan_info *cinfo, u32 msg_hdr, + void *msg_handle) { struct scmi_xfer *xfer; struct device *dev = cinfo->dev; @@ -292,7 +293,7 @@ static void scmi_handle_notification(struct scmi_chan_info *cinfo, u32 msg_hdr) unpack_scmi_header(msg_hdr, &xfer->hdr); scmi_dump_header_dbg(dev, &xfer->hdr); info->desc->ops->fetch_notification(cinfo, info->desc->max_msg_size, - xfer); + xfer, msg_handle); scmi_notify(cinfo->handle, xfer->hdr.protocol_id, xfer->hdr.id, xfer->rx.buf, xfer->rx.len, ts); @@ -305,8 +306,8 @@ static void scmi_handle_notification(struct scmi_chan_info *cinfo, u32 msg_hdr) info->desc->ops->clear_channel(cinfo); } -static void scmi_handle_response(struct scmi_chan_info *cinfo, - u16 xfer_id, u8 msg_type) +static void scmi_handle_response(struct scmi_chan_info *cinfo, u16 xfer_id, + u8 msg_type, void *msg_handle) { struct scmi_xfer *xfer; struct device *dev = cinfo->dev; @@ -339,7 +340,7 @@ static void scmi_handle_response(struct scmi_chan_info *cinfo, scmi_dump_header_dbg(dev, &xfer->hdr); - info->desc->ops->fetch_response(cinfo, xfer); + info->desc->ops->fetch_response(cinfo, xfer, msg_handle); trace_scmi_rx_done(xfer->transfer_id, xfer->hdr.id, xfer->hdr.protocol_id, xfer->hdr.seq, @@ -365,18 +366,19 @@ static void scmi_handle_response(struct scmi_chan_info *cinfo, * NOTE: This function will be invoked in IRQ context, hence should be * as optimal as possible. */ -void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr) +void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr, + void *msg_handle) { u16 xfer_id = MSG_XTRACT_TOKEN(msg_hdr); u8 msg_type = MSG_XTRACT_TYPE(msg_hdr); switch (msg_type) { case MSG_TYPE_NOTIFICATION: - scmi_handle_notification(cinfo, msg_hdr); + scmi_handle_notification(cinfo, msg_hdr, msg_handle); break; case MSG_TYPE_COMMAND: case MSG_TYPE_DELAYED_RESP: - scmi_handle_response(cinfo, xfer_id, msg_type); + scmi_handle_response(cinfo, xfer_id, msg_type, msg_handle); break; default: WARN_ONCE(1, "received unknown msg_type:%d\n", msg_type); @@ -490,7 +492,7 @@ static int do_xfer(const struct scmi_protocol_handle *ph, spin_until_cond(scmi_xfer_done_no_timeout(cinfo, xfer, stop)); if (ktime_before(ktime_get(), stop)) - info->desc->ops->fetch_response(cinfo, xfer); + info->desc->ops->fetch_response(cinfo, xfer, NULL); else ret = -ETIMEDOUT; } else { diff --git a/drivers/firmware/arm_scmi/mailbox.c b/drivers/firmware/arm_scmi/mailbox.c index 4626404be541..584d7dcde2eb 100644 --- a/drivers/firmware/arm_scmi/mailbox.c +++ b/drivers/firmware/arm_scmi/mailbox.c @@ -43,7 +43,7 @@ static void rx_callback(struct mbox_client *cl, void *m) { struct scmi_mailbox *smbox = client_to_scmi_mailbox(cl); - scmi_rx_callback(smbox->cinfo, shmem_read_header(smbox->shmem)); + scmi_rx_callback(smbox->cinfo, shmem_read_header(smbox->shmem), NULL); } static bool mailbox_chan_available(struct device *dev, int idx) @@ -151,7 +151,7 @@ static void mailbox_mark_txdone(struct scmi_chan_info *cinfo, int ret) } static void mailbox_fetch_response(struct scmi_chan_info *cinfo, - struct scmi_xfer *xfer) + struct scmi_xfer *xfer, void *msg_handle) { struct scmi_mailbox *smbox = cinfo->transport_info; @@ -159,7 +159,8 @@ static void mailbox_fetch_response(struct scmi_chan_info *cinfo, } static void mailbox_fetch_notification(struct scmi_chan_info *cinfo, - size_t max_len, struct scmi_xfer *xfer) + size_t max_len, struct scmi_xfer *xfer, + void *msg_handle) { struct scmi_mailbox *smbox = cinfo->transport_info; diff --git a/drivers/firmware/arm_scmi/smc.c b/drivers/firmware/arm_scmi/smc.c index fcbe2677f84b..507107d1a4ad 100644 --- a/drivers/firmware/arm_scmi/smc.c +++ b/drivers/firmware/arm_scmi/smc.c @@ -151,7 +151,8 @@ static int smc_send_message(struct scmi_chan_info *cinfo, if (scmi_info->irq) wait_for_completion(&scmi_info->tx_complete); - scmi_rx_callback(scmi_info->cinfo, shmem_read_header(scmi_info->shmem)); + scmi_rx_callback(scmi_info->cinfo, shmem_read_header(scmi_info->shmem), + NULL); mutex_unlock(&scmi_info->shmem_lock); @@ -162,7 +163,7 @@ static int smc_send_message(struct scmi_chan_info *cinfo, } static void smc_fetch_response(struct scmi_chan_info *cinfo, - struct scmi_xfer *xfer) + struct scmi_xfer *xfer, void *msg_handle) { struct scmi_smc *scmi_info = cinfo->transport_info; From patchwork Tue May 11 00:20:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Hilber X-Patchwork-Id: 434401 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=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 60C0BC43462 for ; Tue, 11 May 2021 00:28:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 29A6061613 for ; Tue, 11 May 2021 00:28:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231254AbhEKA3s (ORCPT ); Mon, 10 May 2021 20:29:48 -0400 Received: from mx1.opensynergy.com ([217.66.60.4]:2477 "EHLO mx1.opensynergy.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231218AbhEKA3o (ORCPT ); Mon, 10 May 2021 20:29:44 -0400 Received: from SR-MAILGATE-02.opensynergy.com (localhost.localdomain [127.0.0.1]) by mx1.opensynergy.com (Proxmox) with ESMTP id C2CE4A1A34; Tue, 11 May 2021 02:22:09 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=opensynergy.com; h=cc:cc:content-transfer-encoding:content-type:content-type :date:from:from:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=srmailgate02; bh=P6aDOohx/CnL NSOtZzTr/KKqECyrpqq0nGc8kYRUUw8=; b=lfOULUUkRdEbM33ODp84rarqB3eL oRp6r512RnPzAuj6sib4ZfsuUKhBSbNM4O9gevs1DpvGU6G1ZmpbjchQRlYTdSjl UJtVwKI9VQgGKGQecHOO2fQ/1xgc4X6iAT2iCDTgppVYbATBFkiJDdaiJXf7enbd kXTPMkLqm82/ZJqxi7yx+nMu11n7tEc26mltk9gQqnUDkfhU8S5Q21i0SOu6poek DJ7ewQhsH9Q5WEmPmbtkkSvd35Z3nvAdkHbetfj90mLhO0bT1w7iolmmePpirYuc iqkBKchUsC6UM5jQzuvNZFRuaQkxPQLOwT3ikbXIqJUB3JlJFPmhlWgw2A== From: Peter Hilber To: , CC: Peter Hilber , Rob Herring , , , , , , , , , Vasyl Vavrychuk , Andriy Tryshnivskyy , Cristian Marussi Subject: [RFC PATCH v3 09/12] firmware: arm_scmi: Add message passing abstractions for transports Date: Tue, 11 May 2021 02:20:37 +0200 Message-ID: <20210511002040.802226-10-peter.hilber@opensynergy.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210511002040.802226-1-peter.hilber@opensynergy.com> References: <20210511002040.802226-1-peter.hilber@opensynergy.com> MIME-Version: 1.0 X-ClientProxiedBy: SR-MAIL-01.open-synergy.com (10.26.10.21) To SR-MAIL-02.open-synergy.com (10.26.10.22) Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Add abstractions for future transports using message passing, such as virtio. Derive the abstractions from the shared memory abstractions. Abstract the transport SDU through the opaque struct scmi_msg_payld. Also enable the transport to determine all other required information about the transport SDU. Signed-off-by: Peter Hilber --- drivers/firmware/Kconfig | 8 +- drivers/firmware/arm_scmi/Makefile | 1 + drivers/firmware/arm_scmi/common.h | 15 ++++ drivers/firmware/arm_scmi/msg.c | 113 +++++++++++++++++++++++++++++ 4 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/arm_scmi/msg.c diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 80ff49dadf35..e8377b12e4d0 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -9,7 +9,7 @@ menu "Firmware Drivers" config ARM_SCMI_PROTOCOL tristate "ARM System Control and Management Interface (SCMI) Message Protocol" depends on ARM || ARM64 || COMPILE_TEST - depends on ARM_SCMI_HAVE_SHMEM + depends on ARM_SCMI_HAVE_SHMEM || ARM_SCMI_HAVE_MSG help ARM System Control and Management Interface (SCMI) protocol is a set of operating system-independent software interfaces that are @@ -33,6 +33,12 @@ config ARM_SCMI_HAVE_SHMEM This declares whether a shared memory based transport for SCMI is available. +config ARM_SCMI_HAVE_MSG + bool + help + This declares whether a message passing based transport for SCMI is + available. + 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 5a2d4c32e0ae..f6b4acb8abdb 100644 --- a/drivers/firmware/arm_scmi/Makefile +++ b/drivers/firmware/arm_scmi/Makefile @@ -4,6 +4,7 @@ scmi-driver-y = driver.o notify.o scmi-transport-$(CONFIG_ARM_SCMI_HAVE_SHMEM) = shmem.o scmi-transport-$(CONFIG_MAILBOX) += mailbox.o scmi-transport-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) += smc.o +scmi-transport-$(CONFIG_ARM_SCMI_HAVE_MSG) += msg.o scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o system.o voltage.o scmi-module-objs := $(scmi-bus-y) $(scmi-driver-y) $(scmi-protocols-y) \ $(scmi-transport-y) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 51ee08bdcb0c..4cb6571c7aaf 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -369,6 +369,21 @@ void shmem_clear_channel(struct scmi_shared_mem __iomem *shmem); bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem, struct scmi_xfer *xfer); +/* declarations for message passing transports */ +struct scmi_msg_payld; + +/** Maximum overhead of message w.r.t. struct scmi_desc.max_msg_size */ +#define SCMI_MSG_MAX_PROT_OVERHEAD (2 * sizeof(__le32)) + +size_t msg_response_size(struct scmi_xfer *xfer); +size_t msg_command_size(struct scmi_xfer *xfer); +void msg_tx_prepare(struct scmi_msg_payld *msg, struct scmi_xfer *xfer); +u32 msg_read_header(struct scmi_msg_payld *msg); +void msg_fetch_response(struct scmi_msg_payld *msg, size_t len, + struct scmi_xfer *xfer); +void msg_fetch_notification(struct scmi_msg_payld *msg, size_t len, + size_t max_len, struct scmi_xfer *xfer); + void scmi_notification_instance_data_set(const struct scmi_handle *handle, void *priv); void *scmi_notification_instance_data_get(const struct scmi_handle *handle); diff --git a/drivers/firmware/arm_scmi/msg.c b/drivers/firmware/arm_scmi/msg.c new file mode 100644 index 000000000000..8a2d3303d281 --- /dev/null +++ b/drivers/firmware/arm_scmi/msg.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * For transports using message passing. + * + * Derived from shm.c. + * + * Copyright (C) 2019 ARM Ltd. + * Copyright (C) 2020 OpenSynergy GmbH + */ + +#include +#include +#include + +#include "common.h" + +/* + * struct scmi_msg_payld - Transport SDU layout + * + * The SCMI specification requires all parameters, message headers, return + * arguments or any protocol data to be expressed in little endian format only. + */ +struct scmi_msg_payld { + __le32 msg_header; + __le32 msg_payload[]; +}; + +/** + * msg_command_size() - Actual size of transport SDU for command. + * + * @xfer: message which core has prepared for sending + * + * Return: transport SDU size. + */ +size_t msg_command_size(struct scmi_xfer *xfer) +{ + return sizeof(struct scmi_msg_payld) + xfer->tx.len; +} + +/** + * msg_response_size() - Maximum size of transport SDU for response. + * + * @xfer: message which core has prepared for sending + * + * Return: transport SDU size. + */ +size_t msg_response_size(struct scmi_xfer *xfer) +{ + return sizeof(struct scmi_msg_payld) + sizeof(__le32) + xfer->rx.len; +} + +/** + * msg_tx_prepare() - Set up transport SDU for command. + * + * @msg: transport SDU for command + * @xfer: message which is being sent + */ +void msg_tx_prepare(struct scmi_msg_payld *msg, struct scmi_xfer *xfer) +{ + msg->msg_header = cpu_to_le32(pack_scmi_header(&xfer->hdr)); + if (xfer->tx.buf) + memcpy(msg->msg_payload, xfer->tx.buf, xfer->tx.len); +} + +/** + * msg_read_header() - Read SCMI header from transport SDU. + * + * @msg: transport SDU + * + * Return: SCMI header + */ +u32 msg_read_header(struct scmi_msg_payld *msg) +{ + return le32_to_cpu(msg->msg_header); +} + +/** + * msg_fetch_response() - Fetch response SCMI payload from transport SDU. + * + * @msg: transport SDU with response + * @len: transport SDU size + * @xfer: message being responded to + */ +void msg_fetch_response(struct scmi_msg_payld *msg, size_t len, + struct scmi_xfer *xfer) +{ + size_t prefix_len = sizeof(*msg) + sizeof(msg->msg_payload[0]); + + xfer->hdr.status = le32_to_cpu(msg->msg_payload[0]); + xfer->rx.len = min_t(size_t, xfer->rx.len, + len >= prefix_len ? len - prefix_len : 0); + + /* Take a copy to the rx buffer.. */ + memcpy(xfer->rx.buf, &msg->msg_payload[1], xfer->rx.len); +} + +/** + * msg_fetch_notification() - Fetch notification payload from transport SDU. + * + * @msg: transport SDU with notification + * @len: transport SDU size + * @max_len: maximum SCMI payload size to fetch + * @xfer: notification message + */ +void msg_fetch_notification(struct scmi_msg_payld *msg, size_t len, + size_t max_len, struct scmi_xfer *xfer) +{ + xfer->rx.len = min_t(size_t, max_len, + len >= sizeof(*msg) ? len - sizeof(*msg) : 0); + + /* Take a copy to the rx buffer.. */ + memcpy(xfer->rx.buf, msg->msg_payload, xfer->rx.len); +} From patchwork Tue May 11 00:20:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Hilber X-Patchwork-Id: 434398 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=-23.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, MENTIONS_GIT_HOSTING, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B0236C43461 for ; Tue, 11 May 2021 00:28:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 85BAB61448 for ; Tue, 11 May 2021 00:28:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231602AbhEKA35 (ORCPT ); Mon, 10 May 2021 20:29:57 -0400 Received: from mx1.opensynergy.com ([217.66.60.4]:16378 "EHLO mx1.opensynergy.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231316AbhEKA3t (ORCPT ); Mon, 10 May 2021 20:29:49 -0400 Received: from SR-MAILGATE-02.opensynergy.com (localhost.localdomain [127.0.0.1]) by mx1.opensynergy.com (Proxmox) with ESMTP id C7CEBA1A38; Tue, 11 May 2021 02:22:12 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=opensynergy.com; h=cc:cc:content-transfer-encoding:content-type:content-type :date:from:from:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=srmailgate02; bh=J1JljJaWo9pg /nozizxGasLsEbgHLupBpRtoFNc0PB8=; b=DjM2RbqAfuCwQd0HA6E1c/ixXcwH dqwhkVJURbCvYtur7qiUJX15KphwjHAd8mEoQlZL1iEAnSBDzH1rukmCxo9zwj77 xoaPRR9vZUbpNu/ixJtNlIql/J0qzj35NKvBLggZe1StKDgsw9ahPnvgsoLBwD8m 5MSwOOT5oXtBRryoiIqUd5ijOwe4FXsueaTmHI+ExJNW1NIWR6/k/0e0Tr2z2VT/ gXGOVaMmTOpYpS0If9MjRYkyu1aCCn7VE9GCKqwwUAfh3DXwH5/2yO5YSH01Pwrs S7X6jyhzln+RM8raoxQhA5gRIfqxb8H77DTmhGwLvhjh2iK3SbME9wExSQ== From: Peter Hilber To: , , , CC: Igor Skalkin , Peter Hilber , Rob Herring , , , , , , , , Vasyl Vavrychuk , Andriy Tryshnivskyy , Cristian Marussi , "Michael S. Tsirkin" , Jason Wang , Viresh Kumar Subject: [RFC PATCH v3 11/12] firmware: arm_scmi: Add virtio transport Date: Tue, 11 May 2021 02:20:39 +0200 Message-ID: <20210511002040.802226-12-peter.hilber@opensynergy.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210511002040.802226-1-peter.hilber@opensynergy.com> References: <20210511002040.802226-1-peter.hilber@opensynergy.com> MIME-Version: 1.0 X-ClientProxiedBy: SR-MAIL-01.open-synergy.com (10.26.10.21) To SR-MAIL-02.open-synergy.com (10.26.10.22) Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Igor Skalkin This transport enables accessing an SCMI platform as a virtio device. Implement an SCMI virtio driver according to the virtio SCMI device spec [1]. Virtio device id 32 has been reserved for the SCMI device [2]. The virtio transport has one Tx channel (virtio cmdq, A2P channel) and at most one Rx channel (virtio eventq, P2A channel). The following feature bit defined in [1] is not implemented: VIRTIO_SCMI_F_SHARED_MEMORY. After the preparatory patches, this implements the virtio transport as paraphrased: Only support a single arm-scmi device (which is consistent with the SCMI spec). scmi-virtio init is called from arm-scmi module init. During the arm-scmi probing, link to the first probed scmi-virtio device. Defer arm-scmi probing if no scmi-virtio device is bound yet. For simplicity, restrict the number of messages which can be pending simultaneously according to the virtqueue capacity. (The virtqueue sizes are negotiated with the virtio device.) As soon as Rx channel message buffers are allocated or have been read out by the arm-scmi driver, feed them to the virtio device. Since some virtio devices may not have the short response time exhibited by SCMI platforms using other transports, set a generous response timeout. Limitations: - Polling is not supported. - The timeout for delayed responses has not been adjusted. [1] https://github.com/oasis-tcs/virtio-spec/blob/master/virtio-scmi.tex [2] https://www.oasis-open.org/committees/ballot.php?id=3496 Signed-off-by: Igor Skalkin [ Peter: Adapted patch for submission to upstream. ] Co-developed-by: Peter Hilber Signed-off-by: Peter Hilber --- MAINTAINERS | 1 + drivers/firmware/Kconfig | 12 + drivers/firmware/arm_scmi/Makefile | 1 + drivers/firmware/arm_scmi/common.h | 3 + drivers/firmware/arm_scmi/driver.c | 3 + drivers/firmware/arm_scmi/virtio.c | 523 +++++++++++++++++++++++++++++ include/uapi/linux/virtio_ids.h | 1 + include/uapi/linux/virtio_scmi.h | 25 ++ 8 files changed, 569 insertions(+) create mode 100644 drivers/firmware/arm_scmi/virtio.c create mode 100644 include/uapi/linux/virtio_scmi.h diff --git a/MAINTAINERS b/MAINTAINERS index bd7aff0c120f..449c336872f3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -17705,6 +17705,7 @@ F: drivers/regulator/scmi-regulator.c F: drivers/reset/reset-scmi.c F: include/linux/sc[mp]i_protocol.h F: include/trace/events/scmi.h +F: include/uapi/linux/virtio_scmi.h SYSTEM RESET/SHUTDOWN DRIVERS M: Sebastian Reichel diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index e8377b12e4d0..7e9eafdd9b63 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -39,6 +39,18 @@ config ARM_SCMI_HAVE_MSG This declares whether a message passing based transport for SCMI is available. +# This config option includes the dependencies of ARM_SCMI_PROTOCOL so that +# this config doesn't show up when SCMI wouldn't be available. +config VIRTIO_SCMI + bool "Virtio transport for SCMI" + select ARM_SCMI_HAVE_MSG + depends on VIRTIO && (ARM || ARM64 || COMPILE_TEST) + help + This enables the virtio based transport for SCMI. + + If you want to use the ARM SCMI protocol between the virtio guest and + a host providing a virtio SCMI device, answer Y. + 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 f6b4acb8abdb..db1787606fb2 100644 --- a/drivers/firmware/arm_scmi/Makefile +++ b/drivers/firmware/arm_scmi/Makefile @@ -5,6 +5,7 @@ scmi-transport-$(CONFIG_ARM_SCMI_HAVE_SHMEM) = shmem.o scmi-transport-$(CONFIG_MAILBOX) += mailbox.o scmi-transport-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) += smc.o scmi-transport-$(CONFIG_ARM_SCMI_HAVE_MSG) += msg.o +scmi-transport-$(CONFIG_VIRTIO_SCMI) += virtio.o scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o system.o voltage.o scmi-module-objs := $(scmi-bus-y) $(scmi-driver-y) $(scmi-protocols-y) \ $(scmi-transport-y) diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h index 4cb6571c7aaf..bada06cfd33d 100644 --- a/drivers/firmware/arm_scmi/common.h +++ b/drivers/firmware/arm_scmi/common.h @@ -349,6 +349,9 @@ extern const struct scmi_desc scmi_mailbox_desc; #ifdef CONFIG_HAVE_ARM_SMCCC extern const struct scmi_desc scmi_smc_desc; #endif +#ifdef CONFIG_VIRTIO_SCMI +extern const struct scmi_desc scmi_virtio_desc; +#endif int scmi_set_transport_info(struct device *dev, void *transport_info); void *scmi_get_transport_info(struct device *dev); diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index e04e7c8e6928..a31187385470 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -1637,6 +1637,9 @@ static const struct of_device_id scmi_of_match[] = { #endif #ifdef CONFIG_HAVE_ARM_SMCCC_DISCOVERY { .compatible = "arm,scmi-smc", .data = &scmi_smc_desc}, +#endif +#ifdef CONFIG_VIRTIO_SCMI + { .compatible = "arm,scmi-virtio", .data = &scmi_virtio_desc}, #endif { /* Sentinel */ }, }; diff --git a/drivers/firmware/arm_scmi/virtio.c b/drivers/firmware/arm_scmi/virtio.c new file mode 100644 index 000000000000..20972adf6dc7 --- /dev/null +++ b/drivers/firmware/arm_scmi/virtio.c @@ -0,0 +1,523 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Virtio Transport driver for Arm System Control and Management Interface + * (SCMI). + * + * Copyright (C) 2020 OpenSynergy. + */ + +/** + * DOC: Theory of Operation + * + * The scmi-virtio transport implements a driver for the virtio SCMI device. + * + * There is one Tx channel (virtio cmdq, A2P channel) and at most one Rx + * channel (virtio eventq, P2A channel). Each channel is implemented through a + * virtqueue. Access to each virtqueue is protected by spinlocks. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +#define VIRTIO_SCMI_MAX_MSG_SIZE 128 /* Value may be increased. */ +#define VIRTIO_SCMI_MAX_PDU_SIZE \ + (VIRTIO_SCMI_MAX_MSG_SIZE + SCMI_MSG_MAX_PROT_OVERHEAD) +#define DESCRIPTORS_PER_TX_MSG 2 + +/** + * struct scmi_vio_channel - Transport channel information + * + * @lock: Protects access to all members except ready. + * @ready_lock: Protects access to ready. If required, it must be taken before + * lock. + * @vqueue: Associated virtqueue + * @cinfo: SCMI Tx or Rx channel + * @free_list: List of unused scmi_vio_msg, maintained for Tx channels only + * @is_rx: Whether channel is an Rx channel + * @ready: Whether transport user is ready to hear about channel + */ +struct scmi_vio_channel { + spinlock_t lock; + spinlock_t ready_lock; + struct virtqueue *vqueue; + struct scmi_chan_info *cinfo; + struct list_head free_list; + u8 is_rx; + u8 ready; +}; + +/** + * struct scmi_vio_msg - Transport PDU information + * + * @request: SDU used for commands + * @input: SDU used for (delayed) responses and notifications + * @list: List which scmi_vio_msg may be part of + * @rx_len: Input SDU size in bytes, once input has been received + */ +struct scmi_vio_msg { + struct scmi_msg_payld *request; + struct scmi_msg_payld *input; + struct list_head list; + unsigned int rx_len; +}; + +static bool scmi_vio_have_vq_rx(struct virtio_device *vdev) +{ + return virtio_has_feature(vdev, VIRTIO_SCMI_F_P2A_CHANNELS); +} + +static int scmi_vio_feed_vq_rx(struct scmi_vio_channel *vioch, + struct scmi_vio_msg *msg) +{ + struct scatterlist sg_in; + int rc; + unsigned long flags; + + sg_init_one(&sg_in, msg->input, VIRTIO_SCMI_MAX_PDU_SIZE); + + spin_lock_irqsave(&vioch->lock, flags); + + rc = virtqueue_add_inbuf(vioch->vqueue, &sg_in, 1, msg, GFP_ATOMIC); + if (rc) + dev_err_once(vioch->cinfo->dev, + "%s() failed to add to virtqueue (%d)\n", __func__, + rc); + else + virtqueue_kick(vioch->vqueue); + + spin_unlock_irqrestore(&vioch->lock, flags); + + return rc; +} + +static void scmi_vio_complete_cb(struct virtqueue *vqueue) +{ + unsigned long ready_flags; + unsigned long flags; + unsigned int length; + struct scmi_vio_channel *vioch; + struct scmi_vio_msg *msg; + bool cb_enabled = true; + + if (WARN_ON_ONCE(!vqueue->vdev->priv)) + return; + vioch = &((struct scmi_vio_channel *)vqueue->vdev->priv)[vqueue->index]; + + for (;;) { + spin_lock_irqsave(&vioch->ready_lock, ready_flags); + + if (!vioch->ready) { + if (!cb_enabled) + (void)virtqueue_enable_cb(vqueue); + goto unlock_ready_out; + } + + spin_lock_irqsave(&vioch->lock, flags); + if (cb_enabled) { + virtqueue_disable_cb(vqueue); + cb_enabled = false; + } + msg = virtqueue_get_buf(vqueue, &length); + if (!msg) { + if (virtqueue_enable_cb(vqueue)) + goto unlock_out; + else + cb_enabled = true; + } + spin_unlock_irqrestore(&vioch->lock, flags); + + if (msg) { + msg->rx_len = length; + + /* + * Hold the ready_lock during the callback to avoid + * races when the arm-scmi driver is unbinding while + * the virtio device is not quiesced yet. + */ + scmi_rx_callback(vioch->cinfo, + msg_read_header(msg->input), msg); + } + spin_unlock_irqrestore(&vioch->ready_lock, ready_flags); + } + +unlock_out: + spin_unlock_irqrestore(&vioch->lock, flags); +unlock_ready_out: + spin_unlock_irqrestore(&vioch->ready_lock, ready_flags); +} + +static const char *const scmi_vio_vqueue_names[] = { "tx", "rx" }; + +static vq_callback_t *scmi_vio_complete_callbacks[] = { + scmi_vio_complete_cb, + scmi_vio_complete_cb +}; + +static unsigned int virtio_get_max_msg(bool tx, + struct scmi_chan_info *base_cinfo) +{ + struct scmi_vio_channel *vioch = base_cinfo->transport_info; + unsigned int ret; + + ret = virtqueue_get_vring_size(vioch->vqueue); + + /* Tx messages need multiple descriptors. */ + if (tx) + ret /= DESCRIPTORS_PER_TX_MSG; + + if (ret > MSG_TOKEN_MAX) { + dev_info_once( + base_cinfo->dev, + "Only %ld messages can be pending simultaneously, while the %s virtqueue could hold %d\n", + MSG_TOKEN_MAX, tx ? "tx" : "rx", ret); + ret = MSG_TOKEN_MAX; + } + + return ret; +} + +static int scmi_vio_match_any_dev(struct device *dev, const void *data) +{ + return 1; +} + +static struct virtio_driver virtio_scmi_driver; /* Forward declaration */ + +static int virtio_link_supplier(struct device *dev) +{ + struct device *vdev = driver_find_device( + &virtio_scmi_driver.driver, NULL, NULL, scmi_vio_match_any_dev); + + if (!vdev) { + dev_notice_once( + dev, + "Deferring probe after not finding a bound scmi-virtio device\n"); + return -EPROBE_DEFER; + } + + /* Add device link for remove order and sysfs link. */ + if (!device_link_add(dev, vdev, DL_FLAG_AUTOREMOVE_CONSUMER)) { + put_device(vdev); + dev_err(dev, "Adding link to supplier virtio device failed\n"); + return -ECANCELED; + } + + put_device(vdev); + return scmi_set_transport_info(dev, dev_to_virtio(vdev)); +} + +static bool virtio_chan_available(struct device *dev, int idx) +{ + struct virtio_device *vdev; + + /* scmi-virtio doesn't support per-protocol channels */ + if (is_scmi_protocol_device(dev)) + return false; + + vdev = scmi_get_transport_info(dev); + if (!vdev) + return false; + + switch (idx) { + case VIRTIO_SCMI_VQ_TX: + return true; + case VIRTIO_SCMI_VQ_RX: + return scmi_vio_have_vq_rx(vdev); + default: + return false; + } +} + +static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, + bool tx) +{ + unsigned long flags; + struct virtio_device *vdev; + struct scmi_vio_channel *vioch; + int index = tx ? VIRTIO_SCMI_VQ_TX : VIRTIO_SCMI_VQ_RX; + int max_msg; + int i; + + if (!virtio_chan_available(dev, index)) + return -ENODEV; + + vdev = scmi_get_transport_info(dev); + vioch = &((struct scmi_vio_channel *)vdev->priv)[index]; + + spin_lock_irqsave(&vioch->lock, flags); + cinfo->transport_info = vioch; + vioch->cinfo = cinfo; + spin_unlock_irqrestore(&vioch->lock, flags); + + max_msg = virtio_get_max_msg(tx, cinfo); + + for (i = 0; i < max_msg; i++) { + struct scmi_vio_msg *msg; + + msg = devm_kzalloc(cinfo->dev, sizeof(*msg), GFP_KERNEL); + if (!msg) + return -ENOMEM; + + if (tx) { + msg->request = devm_kzalloc(cinfo->dev, + VIRTIO_SCMI_MAX_PDU_SIZE, + GFP_KERNEL); + if (!msg->request) + return -ENOMEM; + } + + msg->input = devm_kzalloc(cinfo->dev, VIRTIO_SCMI_MAX_PDU_SIZE, + GFP_KERNEL); + if (!msg->input) + return -ENOMEM; + + if (tx) { + spin_lock_irqsave(&vioch->lock, flags); + list_add_tail(&msg->list, &vioch->free_list); + spin_unlock_irqrestore(&vioch->lock, flags); + } else { + scmi_vio_feed_vq_rx(vioch, msg); + } + } + + spin_lock_irqsave(&vioch->ready_lock, flags); + vioch->ready = true; + spin_unlock_irqrestore(&vioch->ready_lock, flags); + + return 0; +} + +static int virtio_chan_free(int id, void *p, void *data) +{ + unsigned long flags; + struct scmi_chan_info *cinfo = p; + struct scmi_vio_channel *vioch = cinfo->transport_info; + + spin_lock_irqsave(&vioch->ready_lock, flags); + vioch->ready = false; + spin_unlock_irqrestore(&vioch->ready_lock, flags); + + scmi_free_channel(cinfo, data, id); + return 0; +} + +static int virtio_send_message(struct scmi_chan_info *cinfo, + struct scmi_xfer *xfer) +{ + struct scmi_vio_channel *vioch = cinfo->transport_info; + struct scatterlist sg_out; + struct scatterlist sg_in; + struct scatterlist *sgs[DESCRIPTORS_PER_TX_MSG] = { &sg_out, &sg_in }; + unsigned long flags; + int rc; + struct scmi_vio_msg *msg; + + /* + * TODO: For now, we don't support polling. But it should not be + * difficult to add support. + */ + if (xfer->hdr.poll_completion) + return -EINVAL; + + spin_lock_irqsave(&vioch->lock, flags); + + if (list_empty(&vioch->free_list)) { + spin_unlock_irqrestore(&vioch->lock, flags); + return -EBUSY; + } + + msg = list_first_entry(&vioch->free_list, typeof(*msg), list); + list_del(&msg->list); + + msg_tx_prepare(msg->request, xfer); + + sg_init_one(&sg_out, msg->request, msg_command_size(xfer)); + sg_init_one(&sg_in, msg->input, msg_response_size(xfer)); + + rc = virtqueue_add_sgs(vioch->vqueue, sgs, 1, 1, msg, GFP_ATOMIC); + if (rc) { + list_add(&msg->list, &vioch->free_list); + dev_err_once(vioch->cinfo->dev, + "%s() failed to add to virtqueue (%d)\n", __func__, + rc); + } else { + virtqueue_kick(vioch->vqueue); + } + + spin_unlock_irqrestore(&vioch->lock, flags); + + return rc; +} + +static void virtio_fetch_response(struct scmi_chan_info *cinfo, + struct scmi_xfer *xfer, void *msg_handle) +{ + struct scmi_vio_msg *msg = msg_handle; + struct scmi_vio_channel *vioch = cinfo->transport_info; + + if (!msg) { + dev_dbg_once(&vioch->vqueue->vdev->dev, + "Ignoring %s() call with NULL msg_handle\n", + __func__); + return; + } + + msg_fetch_response(msg->input, msg->rx_len, xfer); +} + +static void virtio_fetch_notification(struct scmi_chan_info *cinfo, + size_t max_len, struct scmi_xfer *xfer, + void *msg_handle) +{ + struct scmi_vio_msg *msg = msg_handle; + struct scmi_vio_channel *vioch = cinfo->transport_info; + + if (!msg) { + dev_dbg_once(&vioch->vqueue->vdev->dev, + "Ignoring %s() call with NULL msg_handle\n", + __func__); + return; + } + + msg_fetch_notification(msg->input, msg->rx_len, max_len, xfer); +} + +static void dummy_clear_channel(struct scmi_chan_info *cinfo) +{ +} + +static bool dummy_poll_done(struct scmi_chan_info *cinfo, + struct scmi_xfer *xfer) +{ + return false; +} + +static void virtio_drop_message(struct scmi_chan_info *cinfo, void *msg_handle) +{ + unsigned long flags; + struct scmi_vio_channel *vioch = cinfo->transport_info; + struct scmi_vio_msg *msg = msg_handle; + + if (!msg) { + dev_dbg_once(&vioch->vqueue->vdev->dev, + "Ignoring %s() call with NULL msg_handle\n", + __func__); + return; + } + + if (vioch->is_rx) { + scmi_vio_feed_vq_rx(vioch, msg); + } else { + spin_lock_irqsave(&vioch->lock, flags); + list_add(&msg->list, &vioch->free_list); + spin_unlock_irqrestore(&vioch->lock, flags); + } +} + +static const struct scmi_transport_ops scmi_virtio_ops = { + .link_supplier = virtio_link_supplier, + .chan_available = virtio_chan_available, + .chan_setup = virtio_chan_setup, + .chan_free = virtio_chan_free, + .get_max_msg = virtio_get_max_msg, + .send_message = virtio_send_message, + .fetch_response = virtio_fetch_response, + .fetch_notification = virtio_fetch_notification, + .clear_channel = dummy_clear_channel, + .poll_done = dummy_poll_done, + .drop_message = virtio_drop_message, +}; + +static int scmi_vio_probe(struct virtio_device *vdev) +{ + struct device *dev = &vdev->dev; + struct scmi_vio_channel *channels; + bool have_vq_rx; + int vq_cnt; + int i; + int ret; + struct virtqueue *vqs[VIRTIO_SCMI_VQ_MAX_CNT]; + + have_vq_rx = scmi_vio_have_vq_rx(vdev); + vq_cnt = have_vq_rx ? VIRTIO_SCMI_VQ_MAX_CNT : 1; + + channels = devm_kcalloc(dev, vq_cnt, sizeof(*channels), GFP_KERNEL); + if (!channels) + return -ENOMEM; + + if (have_vq_rx) + channels[VIRTIO_SCMI_VQ_RX].is_rx = true; + + ret = virtio_find_vqs(vdev, vq_cnt, vqs, scmi_vio_complete_callbacks, + scmi_vio_vqueue_names, NULL); + if (ret) { + dev_err(dev, "Failed to get %d virtqueue(s)\n", vq_cnt); + return ret; + } + dev_info(dev, "Found %d virtqueue(s)\n", vq_cnt); + + for (i = 0; i < vq_cnt; i++) { + spin_lock_init(&channels[i].lock); + spin_lock_init(&channels[i].ready_lock); + INIT_LIST_HEAD(&channels[i].free_list); + channels[i].vqueue = vqs[i]; + } + + vdev->priv = channels; + + return 0; +} + +static void scmi_vio_remove(struct virtio_device *vdev) +{ + vdev->config->reset(vdev); + vdev->config->del_vqs(vdev); +} + +static unsigned int features[] = { + VIRTIO_SCMI_F_P2A_CHANNELS, +}; + +static const struct virtio_device_id id_table[] = { + { VIRTIO_ID_SCMI, VIRTIO_DEV_ANY_ID }, + { 0 } +}; + +static struct virtio_driver virtio_scmi_driver = { + .driver.name = "scmi-virtio", + .driver.owner = THIS_MODULE, + .feature_table = features, + .feature_table_size = ARRAY_SIZE(features), + .id_table = id_table, + .probe = scmi_vio_probe, + .remove = scmi_vio_remove, +}; + +static int __init virtio_scmi_init(void) +{ + return register_virtio_driver(&virtio_scmi_driver); +} + +static void __exit virtio_scmi_exit(void) +{ + unregister_virtio_driver(&virtio_scmi_driver); +} + +const struct scmi_desc scmi_virtio_desc = { + .init = virtio_scmi_init, + .exit = virtio_scmi_exit, + .ops = &scmi_virtio_ops, + .max_rx_timeout_ms = 60000, /* for non-realtime virtio devices */ + .max_msg = 0, /* overridden by virtio_get_max_msg() */ + .max_msg_size = VIRTIO_SCMI_MAX_MSG_SIZE, +}; diff --git a/include/uapi/linux/virtio_ids.h b/include/uapi/linux/virtio_ids.h index f0c35ce8628c..c146fe30e589 100644 --- a/include/uapi/linux/virtio_ids.h +++ b/include/uapi/linux/virtio_ids.h @@ -56,5 +56,6 @@ #define VIRTIO_ID_PMEM 27 /* virtio pmem */ #define VIRTIO_ID_BT 28 /* virtio bluetooth */ #define VIRTIO_ID_MAC80211_HWSIM 29 /* virtio mac80211-hwsim */ +#define VIRTIO_ID_SCMI 32 /* virtio SCMI */ #endif /* _LINUX_VIRTIO_IDS_H */ diff --git a/include/uapi/linux/virtio_scmi.h b/include/uapi/linux/virtio_scmi.h new file mode 100644 index 000000000000..732b01504c35 --- /dev/null +++ b/include/uapi/linux/virtio_scmi.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ +/* + * Copyright (C) 2020 OpenSynergy GmbH + */ + +#ifndef _UAPI_LINUX_VIRTIO_SCMI_H +#define _UAPI_LINUX_VIRTIO_SCMI_H + +#include + +/* Feature bits */ + +/* Device implements some SCMI notifications, or delayed responses. */ +#define VIRTIO_SCMI_F_P2A_CHANNELS 0 + +/* Device implements any SCMI statistics shared memory region */ +#define VIRTIO_SCMI_F_SHARED_MEMORY 1 + +/* Virtqueues */ + +#define VIRTIO_SCMI_VQ_TX 0 /* cmdq */ +#define VIRTIO_SCMI_VQ_RX 1 /* eventq */ +#define VIRTIO_SCMI_VQ_MAX_CNT 2 + +#endif /* _UAPI_LINUX_VIRTIO_SCMI_H */