From patchwork Fri Oct 23 00:33:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Ertman X-Patchwork-Id: 11852155 X-Patchwork-Delegate: kuba@kernel.org 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=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, 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 DA3BEC5DF9D for ; Fri, 23 Oct 2020 00:36:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8F77924641 for ; Fri, 23 Oct 2020 00:36:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S373870AbgJWAfa (ORCPT ); Thu, 22 Oct 2020 20:35:30 -0400 Received: from mga11.intel.com ([192.55.52.93]:43009 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2901453AbgJWAfZ (ORCPT ); Thu, 22 Oct 2020 20:35:25 -0400 IronPort-SDR: ipZCRaVb0HyUKR/nBmK+ubIZd6lg0N471x1LwEXRaGGwp2Am5kgvc0OofDZKi2J6CsRe/8sjky PPxj+thj8QlA== X-IronPort-AV: E=McAfee;i="6000,8403,9782"; a="164118638" X-IronPort-AV: E=Sophos;i="5.77,404,1596524400"; d="scan'208";a="164118638" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Oct 2020 17:35:24 -0700 IronPort-SDR: jwomrjVvVE5G/79P2w4YBk87r4nYs91p2cM+SBam5ByjQI+Bx2iYQ6wp7MdCn8KyycWte+KQts o7a3TZATlo+Q== X-IronPort-AV: E=Sophos;i="5.77,404,1596524400"; d="scan'208";a="302505788" Received: from dmert-dev.jf.intel.com ([10.166.241.5]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Oct 2020 17:35:23 -0700 From: Dave Ertman To: alsa-devel@alsa-project.org Cc: tiwai@suse.de, broonie@kernel.org, linux-rdma@vger.kernel.org, jgg@nvidia.com, dledford@redhat.com, netdev@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, gregkh@linuxfoundation.org, ranjani.sridharan@linux.intel.com, pierre-louis.bossart@linux.intel.com, fred.oh@linux.intel.com, parav@mellanox.com, shiraz.saleem@intel.com, dan.j.williams@intel.com, kiran.patil@intel.com, linux-kernel@vger.kernel.org, leonro@nvidia.com Subject: [PATCH v3 02/10] ASoC: SOF: Introduce descriptors for SOF client Date: Thu, 22 Oct 2020 17:33:30 -0700 Message-Id: <20201023003338.1285642-3-david.m.ertman@intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201023003338.1285642-1-david.m.ertman@intel.com> References: <20201023003338.1285642-1-david.m.ertman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Ranjani Sridharan A client in the SOF (Sound Open Firmware) context is a device that needs to communicate with the DSP via IPC messages. The SOF core is responsible for serializing the IPC messages to the DSP from the different clients. One example of an SOF client would be an IPC test client that floods the DSP with test IPC messages to validate if the serialization works as expected. Multi-client support will also add the ability to split the existing audio cards into multiple ones, so as to e.g. to deal with HDMI with a dedicated client instead of adding HDMI to all cards. This patch introduces descriptors for SOF client driver and SOF client device along with APIs for registering and unregistering a SOF client driver, sending IPCs from a client device and accessing the SOF core debugfs root entry. Along with this, add a couple of new members to struct snd_sof_dev that will be used for maintaining the list of clients. Reviewed-by: Pierre-Louis Bossart Signed-off-by: Ranjani Sridharan Co-developed-by: Fred Oh Signed-off-by: Fred Oh Signed-off-by: Dave Ertman --- sound/soc/sof/Kconfig | 19 ++++++ sound/soc/sof/Makefile | 3 + sound/soc/sof/core.c | 2 + sound/soc/sof/sof-client.c | 115 +++++++++++++++++++++++++++++++++++++ sound/soc/sof/sof-client.h | 66 +++++++++++++++++++++ sound/soc/sof/sof-priv.h | 9 +++ 6 files changed, 214 insertions(+) create mode 100644 sound/soc/sof/sof-client.c create mode 100644 sound/soc/sof/sof-client.h diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index 8c1f0829de40..31e9911098fc 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -50,6 +50,24 @@ config SND_SOC_SOF_DEBUG_PROBES Say Y if you want to enable probes. If unsure, select "N". +config SND_SOC_SOF_CLIENT + tristate + select AUXILIARY_BUS + help + This option is not user-selectable but automagically handled by + 'select' statements at a higher level. + +config SND_SOC_SOF_CLIENT_SUPPORT + bool "SOF enable clients" + depends on SND_SOC_SOF + help + This adds support for auxiliary client devices to separate out the debug + functionality for IPC tests, probes etc. into separate devices. This + option would also allow adding client devices based on DSP firmware + capabilities and ACPI/OF device information. + Say Y if you want to enable clients with SOF. + If unsure select "N". + config SND_SOC_SOF_DEVELOPER_SUPPORT bool "SOF developer options support" depends on EXPERT @@ -186,6 +204,7 @@ endif ## SND_SOC_SOF_DEVELOPER_SUPPORT config SND_SOC_SOF tristate + select SND_SOC_SOF_CLIENT if SND_SOC_SOF_CLIENT_SUPPORT select SND_SOC_TOPOLOGY select SND_SOC_SOF_NOCODEC if SND_SOC_SOF_NOCODEC_SUPPORT help diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile index 05718dfe6cd2..5e46f25a3851 100644 --- a/sound/soc/sof/Makefile +++ b/sound/soc/sof/Makefile @@ -2,6 +2,7 @@ snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\ control.o trace.o utils.o sof-audio.o +snd-sof-client-objs := sof-client.o snd-sof-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES) += probe.o compress.o snd-sof-pci-objs := sof-pci-dev.o @@ -18,6 +19,8 @@ obj-$(CONFIG_SND_SOC_SOF_ACPI) += snd-sof-acpi.o obj-$(CONFIG_SND_SOC_SOF_OF) += snd-sof-of.o obj-$(CONFIG_SND_SOC_SOF_PCI) += snd-sof-pci.o +obj-$(CONFIG_SND_SOC_SOF_CLIENT) += snd-sof-client.o + obj-$(CONFIG_SND_SOC_SOF_INTEL_TOPLEVEL) += intel/ obj-$(CONFIG_SND_SOC_SOF_IMX_TOPLEVEL) += imx/ obj-$(CONFIG_SND_SOC_SOF_XTENSA) += xtensa/ diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index adc7c37145d6..72a97219395f 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -314,8 +314,10 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) INIT_LIST_HEAD(&sdev->widget_list); INIT_LIST_HEAD(&sdev->dai_list); INIT_LIST_HEAD(&sdev->route_list); + INIT_LIST_HEAD(&sdev->client_list); spin_lock_init(&sdev->ipc_lock); spin_lock_init(&sdev->hw_lock); + mutex_init(&sdev->client_mutex); if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) INIT_WORK(&sdev->probe_work, sof_probe_work); diff --git a/sound/soc/sof/sof-client.c b/sound/soc/sof/sof-client.c new file mode 100644 index 000000000000..dd75a0ba4c28 --- /dev/null +++ b/sound/soc/sof/sof-client.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan +// + +#include +#include +#include +#include +#include +#include +#include "sof-client.h" +#include "sof-priv.h" + +static void sof_client_auxdev_release(struct device *dev) +{ + struct auxiliary_device *auxdev = to_auxiliary_dev(dev); + struct sof_client_dev *cdev = auxiliary_dev_to_sof_client_dev(auxdev); + + kfree(cdev); +} + +static struct sof_client_dev *sof_client_dev_alloc(struct snd_sof_dev *sdev, const char *name, + u32 id) +{ + struct sof_client_dev *cdev; + struct auxiliary_device *auxdev; + int ret; + + cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); + if (!cdev) + return ERR_PTR(-ENOMEM); + + cdev->sdev = sdev; + auxdev = &cdev->auxdev; + auxdev->name = name; + auxdev->dev.parent = sdev->dev; + auxdev->dev.release = sof_client_auxdev_release; + auxdev->id = id; + + ret = auxiliary_device_init(auxdev); + if (ret < 0) { + dev_err(sdev->dev, "error: failed to initialize client dev %s\n", name); + goto err_free; + } + + return cdev; + +err_free: + kfree(cdev); + return NULL; +} + +int sof_client_dev_register(struct snd_sof_dev *sdev, const char *name, u32 id) +{ + struct sof_client_dev *cdev; + int ret; + + cdev = sof_client_dev_alloc(sdev, name, id); + if (IS_ERR_OR_NULL(cdev)) + return PTR_ERR(cdev); + + ret = auxiliary_device_add(&cdev->auxdev); + if (ret < 0) { + dev_err(sdev->dev, "error: failed to add client dev %s\n", name); + /* cdev will be freed when the release callback is invoked through put_device() */ + auxiliary_device_uninit(&cdev->auxdev); + return ret; + } + + /* add to list of SOF client devices */ + mutex_lock(&sdev->client_mutex); + list_add(&cdev->list, &sdev->client_list); + mutex_unlock(&sdev->client_mutex); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(sof_client_dev_register, SND_SOC_SOF_CLIENT); + +void sof_client_dev_unregister(struct snd_sof_dev *sdev, const char *name, u32 id) +{ + struct sof_client_dev *cdev, *_cdev; + + mutex_lock(&sdev->client_mutex); + + /* cdev will be freed when the release callback for the auxiliary device is invoked */ + list_for_each_entry_safe(cdev, _cdev, &sdev->client_list, list) { + if (!strcmp(cdev->auxdev.name, name) && cdev->auxdev.id == id) { + auxiliary_device_delete(&cdev->auxdev); + auxiliary_device_uninit(&cdev->auxdev); + break; + } + } + + mutex_unlock(&sdev->client_mutex); +} +EXPORT_SYMBOL_NS_GPL(sof_client_dev_unregister, SND_SOC_SOF_CLIENT); + +int sof_client_ipc_tx_message(struct sof_client_dev *cdev, u32 header, void *msg_data, + size_t msg_bytes, void *reply_data, size_t reply_bytes) +{ + return sof_ipc_tx_message(cdev->sdev->ipc, header, msg_data, msg_bytes, + reply_data, reply_bytes); +} +EXPORT_SYMBOL_NS_GPL(sof_client_ipc_tx_message, SND_SOC_SOF_CLIENT); + +struct dentry *sof_client_get_debugfs_root(struct sof_client_dev *cdev) +{ + return cdev->sdev->debugfs_root; +} +EXPORT_SYMBOL_NS_GPL(sof_client_get_debugfs_root, SND_SOC_SOF_CLIENT); + +MODULE_LICENSE("GPL"); diff --git a/sound/soc/sof/sof-client.h b/sound/soc/sof/sof-client.h new file mode 100644 index 000000000000..429282df9f65 --- /dev/null +++ b/sound/soc/sof/sof-client.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __SOUND_SOC_SOF_CLIENT_H +#define __SOUND_SOC_SOF_CLIENT_H + +#include +#include +#include +#include + +#define SOF_CLIENT_PROBE_TIMEOUT_MS 2000 + +struct snd_sof_dev; + +/* SOF client device */ +struct sof_client_dev { + struct auxiliary_device auxdev; + struct snd_sof_dev *sdev; + struct list_head list; /* item in SOF core client dev list */ + void *data; +}; + +/* client-specific ops, all optional */ +struct sof_client_ops { + int (*client_ipc_rx)(struct sof_client_dev *cdev, u32 msg_cmd); +}; + +struct sof_client_drv { + const struct sof_client_ops ops; + struct auxiliary_driver auxiliary_drv; +}; + +#define auxiliary_dev_to_sof_client_dev(auxiliary_dev) \ + container_of(auxiliary_dev, struct sof_client_dev, auxdev) + +static inline int sof_client_drv_register(struct sof_client_drv *drv) +{ + return auxiliary_driver_register(&drv->auxiliary_drv); +} + +static inline void sof_client_drv_unregister(struct sof_client_drv *drv) +{ + auxiliary_driver_unregister(&drv->auxiliary_drv); +} + +int sof_client_dev_register(struct snd_sof_dev *sdev, const char *name, u32 id); +void sof_client_dev_unregister(struct snd_sof_dev *sdev, const char *name, u32 id); + +int sof_client_ipc_tx_message(struct sof_client_dev *cdev, u32 header, void *msg_data, + size_t msg_bytes, void *reply_data, size_t reply_bytes); + +struct dentry *sof_client_get_debugfs_root(struct sof_client_dev *cdev); + +/** + * module_sof_client_driver() - Helper macro for registering an SOF Client + * driver + * @__sof_client_driver: SOF client driver struct + * + * Helper macro for SOF client drivers which do not do anything special in + * module init/exit. This eliminates a lot of boilerplate. Each module may only + * use this macro once, and calling it replaces module_init() and module_exit() + */ +#define module_sof_client_driver(__sof_client_driver) \ + module_driver(__sof_client_driver, sof_client_drv_register, sof_client_drv_unregister) + +#endif diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 0aed2a7ab858..dceac73b858f 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -442,6 +442,15 @@ struct snd_sof_dev { bool msi_enabled; + /* + * Used to keep track of registered client devices so that they can be removed when the + * parent SOF module is removed. + */ + struct list_head client_list; + + /* mutex to protect client list */ + struct mutex client_mutex; + void *private; /* core does not touch this */ }; From patchwork Fri Oct 23 00:33:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Ertman X-Patchwork-Id: 11852153 X-Patchwork-Delegate: kuba@kernel.org 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=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, 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 515F8C56201 for ; Fri, 23 Oct 2020 00:35:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0086E24641 for ; Fri, 23 Oct 2020 00:35:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S373881AbgJWAfb (ORCPT ); Thu, 22 Oct 2020 20:35:31 -0400 Received: from mga11.intel.com ([192.55.52.93]:43016 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S373846AbgJWAfZ (ORCPT ); Thu, 22 Oct 2020 20:35:25 -0400 IronPort-SDR: UT11oQCBQgfyjvpyICtZd7k7JozPREtqM3JDx3BRZf7dK/XqWgCTmc9XLH27LBEFTd+HKtZ9tZ rT4wblbP612w== X-IronPort-AV: E=McAfee;i="6000,8403,9782"; a="164118641" X-IronPort-AV: E=Sophos;i="5.77,404,1596524400"; d="scan'208";a="164118641" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Oct 2020 17:35:24 -0700 IronPort-SDR: uEJ6hxlo7ljJWh1ViCqKJsOSsOfdaTyANaVg50VL+GJJJp/sYXzONyFrsrlaKXRztEi+lkswCy f3gT5ilxfS5Q== X-IronPort-AV: E=Sophos;i="5.77,404,1596524400"; d="scan'208";a="302505795" Received: from dmert-dev.jf.intel.com ([10.166.241.5]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Oct 2020 17:35:24 -0700 From: Dave Ertman To: alsa-devel@alsa-project.org Cc: tiwai@suse.de, broonie@kernel.org, linux-rdma@vger.kernel.org, jgg@nvidia.com, dledford@redhat.com, netdev@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, gregkh@linuxfoundation.org, ranjani.sridharan@linux.intel.com, pierre-louis.bossart@linux.intel.com, fred.oh@linux.intel.com, parav@mellanox.com, shiraz.saleem@intel.com, dan.j.williams@intel.com, kiran.patil@intel.com, linux-kernel@vger.kernel.org, leonro@nvidia.com Subject: [PATCH v3 03/10] ASoC: SOF: Create client driver for IPC test Date: Thu, 22 Oct 2020 17:33:31 -0700 Message-Id: <20201023003338.1285642-4-david.m.ertman@intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201023003338.1285642-1-david.m.ertman@intel.com> References: <20201023003338.1285642-1-david.m.ertman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Ranjani Sridharan Create an SOF client driver for IPC flood test. This driver is used to set up the debugfs entries and the read/write ops for initiating the IPC flood test that would be used to measure the min/max/avg response times for sending IPCs to the DSP. The debugfs ops definitions in the driver is existing code that has been copied from the core. These will be removed from the SOF core making is less monolithic and easier to maintain. Reviewed-by: Pierre-Louis Bossart Signed-off-by: Ranjani Sridharan Co-developed-by: Fred Oh Signed-off-by: Fred Oh Signed-off-by: Dave Ertman --- sound/soc/sof/Kconfig | 10 + sound/soc/sof/Makefile | 4 + sound/soc/sof/sof-ipc-test-client.c | 321 ++++++++++++++++++++++++++++ 3 files changed, 335 insertions(+) create mode 100644 sound/soc/sof/sof-ipc-test-client.c diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index 31e9911098fc..13bde36cc5d7 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -190,6 +190,16 @@ config SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST Say Y if you want to enable IPC flood test. If unsure, select "N". +config SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST_CLIENT + tristate "SOF enable IPC flood test client" + depends on SND_SOC_SOF_CLIENT + help + This option enables a separate client device for IPC flood test + which can be used to flood the DSP with test IPCs and gather stats + about response times. + Say Y if you want to enable IPC flood test. + If unsure, select "N". + config SND_SOC_SOF_DEBUG_RETAIN_DSP_CONTEXT bool "SOF retain DSP context on any FW exceptions" help diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile index 5e46f25a3851..baa93fe2cc9a 100644 --- a/sound/soc/sof/Makefile +++ b/sound/soc/sof/Makefile @@ -9,6 +9,8 @@ snd-sof-pci-objs := sof-pci-dev.o snd-sof-acpi-objs := sof-acpi-dev.o snd-sof-of-objs := sof-of-dev.o +snd-sof-ipc-test-objs := sof-ipc-test-client.o + snd-sof-nocodec-objs := nocodec.o obj-$(CONFIG_SND_SOC_SOF) += snd-sof.o @@ -21,6 +23,8 @@ obj-$(CONFIG_SND_SOC_SOF_PCI) += snd-sof-pci.o obj-$(CONFIG_SND_SOC_SOF_CLIENT) += snd-sof-client.o +obj-$(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST_CLIENT) += snd-sof-ipc-test.o + obj-$(CONFIG_SND_SOC_SOF_INTEL_TOPLEVEL) += intel/ obj-$(CONFIG_SND_SOC_SOF_IMX_TOPLEVEL) += imx/ obj-$(CONFIG_SND_SOC_SOF_XTENSA) += xtensa/ diff --git a/sound/soc/sof/sof-ipc-test-client.c b/sound/soc/sof/sof-ipc-test-client.c new file mode 100644 index 000000000000..b4d803b9139b --- /dev/null +++ b/sound/soc/sof/sof-ipc-test-client.c @@ -0,0 +1,321 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sof-client.h" + +#define MAX_IPC_FLOOD_DURATION_MS 1000 +#define MAX_IPC_FLOOD_COUNT 10000 +#define IPC_FLOOD_TEST_RESULT_LEN 512 +#define SOF_IPC_CLIENT_SUSPEND_DELAY_MS 3000 + +struct sof_ipc_client_data { + struct dentry *dfs_root; + char *buf; +}; + +/* + * helper function to perform the flood test. Only one of the two params, ipc_duration_ms + * or ipc_count, will be non-zero and will determine the type of test + */ +static int sof_debug_ipc_flood_test(struct sof_client_dev *cdev, unsigned long ipc_duration_ms, + unsigned long ipc_count) +{ + struct sof_ipc_client_data *ipc_client_data = cdev->data; + struct device *dev = &cdev->auxdev.dev; + struct sof_ipc_cmd_hdr hdr; + struct sof_ipc_reply reply; + u64 min_response_time = U64_MAX; + u64 avg_response_time = 0; + u64 max_response_time = 0; + ktime_t cur; + ktime_t test_end; + int i = 0; + int ret = 0; + bool end_test = false; + + /* configure test IPC */ + hdr.cmd = SOF_IPC_GLB_TEST_MSG | SOF_IPC_TEST_IPC_FLOOD; + hdr.size = sizeof(hdr); + + /* set test end time for duration flood test */ + test_end = ktime_get_ns() + ipc_duration_ms * NSEC_PER_MSEC; + + /* send test IPC's */ + do { + ktime_t start; + u64 ipc_response_time; + + start = ktime_get(); + ret = sof_client_ipc_tx_message(cdev, hdr.cmd, &hdr, hdr.size, &reply, + sizeof(reply)); + if (ret < 0) + break; + cur = ktime_get(); + + i++; + + /* compute min and max response times */ + ipc_response_time = ktime_to_ns(ktime_sub(cur, start)); + min_response_time = min(min_response_time, ipc_response_time); + max_response_time = max(max_response_time, ipc_response_time); + + /* sum up response times */ + avg_response_time += ipc_response_time; + + /* end test? */ + if (ipc_count && i == ipc_count) + end_test = true; + else if (ipc_duration_ms && (ktime_to_ns(cur) >= test_end)) + end_test = true; + + } while (!end_test); + + if (ret < 0) + return ret; + + /* return if the first IPC fails */ + if (!i) + return ret; + + /* compute average response time */ + DIV_ROUND_CLOSEST(avg_response_time, i); + + /* clear previous test output */ + memset(ipc_client_data->buf, 0, IPC_FLOOD_TEST_RESULT_LEN); + + if (!ipc_count) { + dev_dbg(dev, "IPC Flood test duration: %lums\n", ipc_duration_ms); + snprintf(ipc_client_data->buf, IPC_FLOOD_TEST_RESULT_LEN, + "IPC Flood test duration: %lums\n", ipc_duration_ms); + } + + dev_dbg(dev, + "IPC Flood count: %d, Avg response time: %lluns\n", i, avg_response_time); + dev_dbg(dev, "Max response time: %lluns\n", max_response_time); + dev_dbg(dev, "Min response time: %lluns\n", min_response_time); + + /* format output string and save test results */ + snprintf(ipc_client_data->buf + strlen(ipc_client_data->buf), + IPC_FLOOD_TEST_RESULT_LEN - strlen(ipc_client_data->buf), + "IPC Flood count: %d\nAvg response time: %lluns\n", i, avg_response_time); + + snprintf(ipc_client_data->buf + strlen(ipc_client_data->buf), + IPC_FLOOD_TEST_RESULT_LEN - strlen(ipc_client_data->buf), + "Max response time: %lluns\nMin response time: %lluns\n", + max_response_time, min_response_time); + + return ret; +} + +/* + * Writing to the debugfs entry initiates the IPC flood test based on + * the IPC count or the duration specified by the user. + */ +static ssize_t sof_ipc_dfsentry_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) +{ + struct dentry *dentry = file->f_path.dentry; + struct sof_client_dev *cdev = file->private_data; + struct device *dev = &cdev->auxdev.dev; + unsigned long ipc_duration_ms = 0; + bool flood_duration_test; + unsigned long ipc_count = 0; + char *string; + size_t size; + int err; + int ret; + + string = kzalloc(count, GFP_KERNEL); + if (!string) + return -ENOMEM; + + size = simple_write_to_buffer(string, count, ppos, buffer, count); + + flood_duration_test = !strcmp(dentry->d_name.name, "ipc_flood_duration_ms"); + + /* limit max duration/ipc count for flood test */ + if (flood_duration_test) { + ret = kstrtoul(string, 0, &ipc_duration_ms); + if (ret < 0) + goto out; + + if (!ipc_duration_ms) { + ret = size; + goto out; + } + + ipc_duration_ms = min_t(unsigned long, ipc_duration_ms, MAX_IPC_FLOOD_DURATION_MS); + } else { + ret = kstrtoul(string, 0, &ipc_count); + if (ret < 0) + goto out; + + if (!ipc_count) { + ret = size; + goto out; + } + + ipc_count = min_t(unsigned long, ipc_count, MAX_IPC_FLOOD_COUNT); + } + + ret = pm_runtime_get_sync(dev); + if (ret < 0 && ret != -EACCES) { + dev_err_ratelimited(dev, "error: debugfs write failed to resume %d\n", ret); + pm_runtime_put_noidle(dev); + goto out; + } + + ret = sof_debug_ipc_flood_test(cdev, ipc_duration_ms, ipc_count); + + pm_runtime_mark_last_busy(dev); + err = pm_runtime_put_autosuspend(dev); + if (err < 0) { + ret = err; + goto out; + } + + /* return size if test is successful */ + if (ret >= 0) + ret = size; +out: + kfree(string); + return ret; +} + +/* return the result of the last IPC flood test */ +static ssize_t sof_ipc_dfsentry_read(struct file *file, char __user *buffer, + size_t count, loff_t *ppos) +{ + struct sof_client_dev *cdev = file->private_data; + struct sof_ipc_client_data *ipc_client_data = cdev->data; + size_t size_ret; + + if (*ppos) + return 0; + + /* return results of the last IPC test */ + count = min_t(size_t, count, strlen(ipc_client_data->buf)); + size_ret = copy_to_user(buffer, ipc_client_data->buf, count); + if (size_ret) + return -EFAULT; + + *ppos += count; + return count; +} + +static const struct file_operations sof_ipc_dfs_fops = { + .open = simple_open, + .read = sof_ipc_dfsentry_read, + .llseek = default_llseek, + .write = sof_ipc_dfsentry_write, +}; + +/* + * The IPC test client creates a couple of debugfs entries that will be used + * flood tests. Users can write to these entries to execute the IPC flood test + * by specifying either the number of IPCs to flood the DSP with or the duration + * (in ms) for which the DSP should be flooded with test IPCs. At the + * end of each test, the average, min and max response times are reported back. + * The results of the last flood test can be accessed by reading the debugfs + * entries. + */ +static int sof_ipc_test_probe(struct auxiliary_device *auxdev, + const struct auxiliary_device_id *id) +{ + struct sof_client_dev *cdev = auxiliary_dev_to_sof_client_dev(auxdev); + struct sof_ipc_client_data *ipc_client_data; + + /* allocate memory for client data */ + ipc_client_data = devm_kzalloc(&auxdev->dev, sizeof(*ipc_client_data), GFP_KERNEL); + if (!ipc_client_data) + return -ENOMEM; + + ipc_client_data->buf = devm_kzalloc(&auxdev->dev, IPC_FLOOD_TEST_RESULT_LEN, GFP_KERNEL); + if (!ipc_client_data->buf) + return -ENOMEM; + + cdev->data = ipc_client_data; + + /* create debugfs root folder with device name under parent SOF dir */ + ipc_client_data->dfs_root = debugfs_create_dir(dev_name(&auxdev->dev), + sof_client_get_debugfs_root(cdev)); + + /* create read-write ipc_flood_count debugfs entry */ + debugfs_create_file("ipc_flood_count", 0644, ipc_client_data->dfs_root, + cdev, &sof_ipc_dfs_fops); + + /* create read-write ipc_flood_duration_ms debugfs entry */ + debugfs_create_file("ipc_flood_duration_ms", 0644, ipc_client_data->dfs_root, + cdev, &sof_ipc_dfs_fops); + + /* enable runtime PM */ + pm_runtime_set_autosuspend_delay(&auxdev->dev, SOF_IPC_CLIENT_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(&auxdev->dev); + pm_runtime_enable(&auxdev->dev); + pm_runtime_mark_last_busy(&auxdev->dev); + pm_runtime_idle(&auxdev->dev); + + return 0; +} + +static int sof_ipc_test_cleanup(struct auxiliary_device *auxdev) +{ + struct sof_client_dev *cdev = auxiliary_dev_to_sof_client_dev(auxdev); + struct sof_ipc_client_data *ipc_client_data = cdev->data; + + pm_runtime_disable(&auxdev->dev); + + debugfs_remove_recursive(ipc_client_data->dfs_root); + + return 0; +} + +static int sof_ipc_test_remove(struct auxiliary_device *auxdev) +{ + return sof_ipc_test_cleanup(auxdev); +} + +static void sof_ipc_test_shutdown(struct auxiliary_device *auxdev) +{ + sof_ipc_test_cleanup(auxdev); +} + +static const struct auxiliary_device_id sof_ipc_auxbus_id_table[] = { + { .name = "snd_sof_client.ipc_test" }, + {}, +}; +MODULE_DEVICE_TABLE(auxiliary, sof_ipc_auxbus_id_table); + +/* + * No need for driver pm_ops as the generic pm callbacks in the auxiliary bus type are enough to + * ensure that the parent SOF device resumes to bring the DSP back to D0. + * driver name will be set based on KBUILD_MODNAME. + */ +static struct sof_client_drv sof_ipc_test_client_drv = { + .auxiliary_drv = { + .id_table = sof_ipc_auxbus_id_table, + .probe = sof_ipc_test_probe, + .remove = sof_ipc_test_remove, + .shutdown = sof_ipc_test_shutdown, + }, +}; + +module_sof_client_driver(sof_ipc_test_client_drv); + +MODULE_DESCRIPTION("SOF IPC Test Client Driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT); From patchwork Fri Oct 23 00:33:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Ertman X-Patchwork-Id: 11852147 X-Patchwork-Delegate: kuba@kernel.org 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=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, 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 1E230C55179 for ; Fri, 23 Oct 2020 00:35:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D1FA5223C7 for ; Fri, 23 Oct 2020 00:35:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S373892AbgJWAfd (ORCPT ); Thu, 22 Oct 2020 20:35:33 -0400 Received: from mga11.intel.com ([192.55.52.93]:43018 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S373852AbgJWAf0 (ORCPT ); Thu, 22 Oct 2020 20:35:26 -0400 IronPort-SDR: G8BObdC6OAvMiB0YodMFt+DdpEpUJQXAUsIEWUZVFXC2y9n5fob44APavaiZ/n5Vg/XUt0yxTY Od4GAK6Y1tiw== X-IronPort-AV: E=McAfee;i="6000,8403,9782"; a="164118643" X-IronPort-AV: E=Sophos;i="5.77,404,1596524400"; d="scan'208";a="164118643" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Oct 2020 17:35:25 -0700 IronPort-SDR: OTeiAXI1PaLWopJs+ay0MQ1U8VXU8WDVreh8x0jGpz4jL73ZAIqFBKK8Hvljt6XKW5esYGZEPv y13NwTARxp8Q== X-IronPort-AV: E=Sophos;i="5.77,404,1596524400"; d="scan'208";a="302505801" Received: from dmert-dev.jf.intel.com ([10.166.241.5]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Oct 2020 17:35:24 -0700 From: Dave Ertman To: alsa-devel@alsa-project.org Cc: tiwai@suse.de, broonie@kernel.org, linux-rdma@vger.kernel.org, jgg@nvidia.com, dledford@redhat.com, netdev@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, gregkh@linuxfoundation.org, ranjani.sridharan@linux.intel.com, pierre-louis.bossart@linux.intel.com, fred.oh@linux.intel.com, parav@mellanox.com, shiraz.saleem@intel.com, dan.j.williams@intel.com, kiran.patil@intel.com, linux-kernel@vger.kernel.org, leonro@nvidia.com Subject: [PATCH v3 04/10] ASoC: SOF: ops: Add ops for client registration Date: Thu, 22 Oct 2020 17:33:32 -0700 Message-Id: <20201023003338.1285642-5-david.m.ertman@intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201023003338.1285642-1-david.m.ertman@intel.com> References: <20201023003338.1285642-1-david.m.ertman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Ranjani Sridharan Add new ops for registering/unregistering clients based on DSP capabilities and/or DT information. Reviewed-by: Pierre-Louis Bossart Signed-off-by: Ranjani Sridharan Signed-off-by: Dave Ertman --- sound/soc/sof/core.c | 10 ++++++++++ sound/soc/sof/ops.h | 14 ++++++++++++++ sound/soc/sof/sof-priv.h | 4 ++++ 3 files changed, 28 insertions(+) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 72a97219395f..ddb9a12d5aac 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -246,8 +246,17 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) if (plat_data->sof_probe_complete) plat_data->sof_probe_complete(sdev->dev); + /* If registering certain clients fails, unregister the previously registered clients. */ + ret = snd_sof_register_clients(sdev); + if (ret < 0) { + dev_err(sdev->dev, "error: failed to register clients %d\n", ret); + goto client_reg_err; + } + return 0; +client_reg_err: + snd_sof_unregister_clients(sdev); fw_trace_err: snd_sof_free_trace(sdev); fw_run_err: @@ -356,6 +365,7 @@ int snd_sof_device_remove(struct device *dev) dev_warn(dev, "error: %d failed to prepare DSP for device removal", ret); + snd_sof_unregister_clients(sdev); snd_sof_fw_unload(sdev); snd_sof_ipc_free(sdev); snd_sof_free_debug(sdev); diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index b21632f5511a..00370f8bcd75 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -470,6 +470,20 @@ snd_sof_set_mach_params(const struct snd_soc_acpi_mach *mach, sof_ops(sdev)->set_mach_params(mach, dev); } +static inline int snd_sof_register_clients(struct snd_sof_dev *sdev) +{ + if (sof_ops(sdev) && sof_ops(sdev)->register_clients) + return sof_ops(sdev)->register_clients(sdev); + + return 0; +} + +static inline void snd_sof_unregister_clients(struct snd_sof_dev *sdev) +{ + if (sof_ops(sdev) && sof_ops(sdev)->unregister_clients) + sof_ops(sdev)->unregister_clients(sdev); +} + static inline const struct snd_sof_dsp_ops *sof_get_ops(const struct sof_dev_desc *d, const struct sof_ops_table mach_ops[], int asize) diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index dceac73b858f..cca239c09d0e 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -252,6 +252,10 @@ struct snd_sof_dsp_ops { void (*set_mach_params)(const struct snd_soc_acpi_mach *mach, struct device *dev); /* optional */ + /* client ops */ + int (*register_clients)(struct snd_sof_dev *sdev); /* optional */ + void (*unregister_clients)(struct snd_sof_dev *sdev); /* optional */ + /* DAI ops */ struct snd_soc_dai_driver *drv; int num_drv; From patchwork Fri Oct 23 00:33:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Ertman X-Patchwork-Id: 11852151 X-Patchwork-Delegate: kuba@kernel.org 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=-9.9 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY,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 7F389C388F7 for ; Fri, 23 Oct 2020 00:35:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2758124650 for ; Fri, 23 Oct 2020 00:35:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S373901AbgJWAfe (ORCPT ); Thu, 22 Oct 2020 20:35:34 -0400 Received: from mga11.intel.com ([192.55.52.93]:43009 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S373770AbgJWAf3 (ORCPT ); Thu, 22 Oct 2020 20:35:29 -0400 IronPort-SDR: rrERpKOvlna9bh5Q3qTVaYESJRmDBkNYJteJ8RUUH1QwieL3XtMMXuAXMdLO0hfUVeqMZ95ktg FbFxb7PNSTQw== X-IronPort-AV: E=McAfee;i="6000,8403,9782"; a="164118645" X-IronPort-AV: E=Sophos;i="5.77,404,1596524400"; d="scan'208";a="164118645" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Oct 2020 17:35:26 -0700 IronPort-SDR: GOPPfUznrnoPCOI9L3kQiMf5F77UMC0HoNYLxnOlb2ufHHRUanNBzi0ieX3myL2ArMV1jOUkik ue2i8R4Wr5FQ== X-IronPort-AV: E=Sophos;i="5.77,404,1596524400"; d="scan'208";a="302505806" Received: from dmert-dev.jf.intel.com ([10.166.241.5]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Oct 2020 17:35:25 -0700 From: Dave Ertman To: alsa-devel@alsa-project.org Cc: tiwai@suse.de, broonie@kernel.org, linux-rdma@vger.kernel.org, jgg@nvidia.com, dledford@redhat.com, netdev@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, gregkh@linuxfoundation.org, ranjani.sridharan@linux.intel.com, pierre-louis.bossart@linux.intel.com, fred.oh@linux.intel.com, parav@mellanox.com, shiraz.saleem@intel.com, dan.j.williams@intel.com, kiran.patil@intel.com, linux-kernel@vger.kernel.org, leonro@nvidia.com Subject: [PATCH v3 05/10] ASoC: SOF: Intel: Define ops for client registration Date: Thu, 22 Oct 2020 17:33:33 -0700 Message-Id: <20201023003338.1285642-6-david.m.ertman@intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201023003338.1285642-1-david.m.ertman@intel.com> References: <20201023003338.1285642-1-david.m.ertman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Ranjani Sridharan Define client ops for Intel platforms. For now, we only add 2 IPC test clients that will be used for run tandem IPC flood tests for. For ACPI platforms, change the Kconfig to select SND_SOC_SOF_PROBE_WORK_QUEUE to allow the ancillary driver to probe when the client is registered. Reviewed-by: Pierre-Louis Bossart Signed-off-by: Ranjani Sridharan Co-developed-by: Fred Oh Signed-off-by: Fred Oh Signed-off-by: Dave Ertman --- sound/soc/sof/intel/Kconfig | 9 +++++++ sound/soc/sof/intel/Makefile | 3 +++ sound/soc/sof/intel/apl.c | 16 ++++++++++++ sound/soc/sof/intel/bdw.c | 16 ++++++++++++ sound/soc/sof/intel/byt.c | 20 +++++++++++++++ sound/soc/sof/intel/cnl.c | 16 ++++++++++++ sound/soc/sof/intel/intel-client.c | 40 ++++++++++++++++++++++++++++++ sound/soc/sof/intel/intel-client.h | 26 +++++++++++++++++++ 8 files changed, 146 insertions(+) create mode 100644 sound/soc/sof/intel/intel-client.c create mode 100644 sound/soc/sof/intel/intel-client.h diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index a066e08860cb..b449fa2f8005 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -13,6 +13,8 @@ config SND_SOC_SOF_INTEL_ACPI def_tristate SND_SOC_SOF_ACPI select SND_SOC_SOF_BAYTRAIL if SND_SOC_SOF_BAYTRAIL_SUPPORT select SND_SOC_SOF_BROADWELL if SND_SOC_SOF_BROADWELL_SUPPORT + select SND_SOC_SOF_PROBE_WORK_QUEUE if SND_SOC_SOF_CLIENT + select SND_SOC_SOF_INTEL_CLIENT if SND_SOC_SOF_CLIENT help This option is not user-selectable but automagically handled by 'select' statements at a higher level @@ -29,6 +31,7 @@ config SND_SOC_SOF_INTEL_PCI select SND_SOC_SOF_TIGERLAKE if SND_SOC_SOF_TIGERLAKE_SUPPORT select SND_SOC_SOF_ELKHARTLAKE if SND_SOC_SOF_ELKHARTLAKE_SUPPORT select SND_SOC_SOF_JASPERLAKE if SND_SOC_SOF_JASPERLAKE_SUPPORT + select SND_SOC_SOF_INTEL_CLIENT if SND_SOC_SOF_CLIENT help This option is not user-selectable but automagically handled by 'select' statements at a higher level @@ -57,6 +60,12 @@ config SND_SOC_SOF_INTEL_COMMON This option is not user-selectable but automagically handled by 'select' statements at a higher level +config SND_SOC_SOF_INTEL_CLIENT + tristate + help + This option is not user-selectable but automagically handled by + 'select' statements at a higher level. + if SND_SOC_SOF_INTEL_ACPI config SND_SOC_SOF_BAYTRAIL_SUPPORT diff --git a/sound/soc/sof/intel/Makefile b/sound/soc/sof/intel/Makefile index 72d85b25df7d..683e64c627c1 100644 --- a/sound/soc/sof/intel/Makefile +++ b/sound/soc/sof/intel/Makefile @@ -5,6 +5,8 @@ snd-sof-intel-bdw-objs := bdw.o snd-sof-intel-ipc-objs := intel-ipc.o +snd-sof-intel-client-objs := intel-client.o + snd-sof-intel-hda-common-objs := hda.o hda-loader.o hda-stream.o hda-trace.o \ hda-dsp.o hda-ipc.o hda-ctrl.o hda-pcm.o \ hda-dai.o hda-bus.o \ @@ -18,3 +20,4 @@ obj-$(CONFIG_SND_SOC_SOF_BROADWELL) += snd-sof-intel-bdw.o obj-$(CONFIG_SND_SOC_SOF_INTEL_HIFI_EP_IPC) += snd-sof-intel-ipc.o obj-$(CONFIG_SND_SOC_SOF_HDA_COMMON) += snd-sof-intel-hda-common.o obj-$(CONFIG_SND_SOC_SOF_HDA) += snd-sof-intel-hda.o +obj-$(CONFIG_SND_SOC_SOF_INTEL_CLIENT) += snd-sof-intel-client.o diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index 4eeade2e77f7..ce2dcd6aa7de 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -18,6 +18,7 @@ #include "../sof-priv.h" #include "hda.h" #include "../sof-audio.h" +#include "intel-client.h" static const struct snd_sof_debugfs_map apl_dsp_debugfs[] = { {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS}, @@ -25,6 +26,16 @@ static const struct snd_sof_debugfs_map apl_dsp_debugfs[] = { {"dsp", HDA_DSP_BAR, 0, 0x10000, SOF_DEBUGFS_ACCESS_ALWAYS}, }; +static int apl_register_clients(struct snd_sof_dev *sdev) +{ + return intel_register_ipc_test_clients(sdev); +} + +static void apl_unregister_clients(struct snd_sof_dev *sdev) +{ + intel_unregister_ipc_test_clients(sdev); +} + /* apollolake ops */ const struct snd_sof_dsp_ops sof_apl_ops = { /* probe and remove */ @@ -101,6 +112,10 @@ const struct snd_sof_dsp_ops sof_apl_ops = { .trace_release = hda_dsp_trace_release, .trace_trigger = hda_dsp_trace_trigger, + /* client ops */ + .register_clients = apl_register_clients, + .unregister_clients = apl_unregister_clients, + /* DAI drivers */ .drv = skl_dai, .num_drv = SOF_SKL_NUM_DAIS, @@ -140,3 +155,4 @@ const struct sof_intel_dsp_desc apl_chip_info = { .ssp_base_offset = APL_SSP_BASE_OFFSET, }; EXPORT_SYMBOL_NS(apl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); +MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_CLIENT); diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index 50a4a73e6b9f..d6fb5e228e93 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -18,6 +18,7 @@ #include "../ops.h" #include "shim.h" #include "../sof-audio.h" +#include "intel-client.h" /* BARs */ #define BDW_DSP_BAR 0 @@ -563,6 +564,16 @@ static void bdw_set_mach_params(const struct snd_soc_acpi_mach *mach, mach_params->platform = dev_name(dev); } +static int bdw_register_clients(struct snd_sof_dev *sdev) +{ + return intel_register_ipc_test_clients(sdev); +} + +static void bdw_unregister_clients(struct snd_sof_dev *sdev) +{ + intel_unregister_ipc_test_clients(sdev); +} + /* Broadwell DAIs */ static struct snd_soc_dai_driver bdw_dai[] = { { @@ -638,6 +649,10 @@ const struct snd_sof_dsp_ops sof_bdw_ops = { /*Firmware loading */ .load_firmware = snd_sof_load_firmware_memcpy, + /* client ops */ + .register_clients = bdw_register_clients, + .unregister_clients = bdw_unregister_clients, + /* DAI drivers */ .drv = bdw_dai, .num_drv = ARRAY_SIZE(bdw_dai), @@ -662,3 +677,4 @@ EXPORT_SYMBOL_NS(bdw_chip_info, SND_SOC_SOF_BROADWELL); MODULE_LICENSE("Dual BSD/GPL"); MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HIFI_EP_IPC); MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA); +MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_CLIENT); diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 186736ee5fc2..a42820606ace 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -19,6 +19,7 @@ #include "shim.h" #include "../sof-audio.h" #include "../../intel/common/soc-intel-quirks.h" +#include "intel-client.h" /* DSP memories */ #define IRAM_OFFSET 0x0C0000 @@ -821,6 +822,16 @@ static int byt_acpi_probe(struct snd_sof_dev *sdev) return ret; } +static int byt_register_clients(struct snd_sof_dev *sdev) +{ + return intel_register_ipc_test_clients(sdev); +} + +static void byt_unregister_clients(struct snd_sof_dev *sdev) +{ + intel_unregister_ipc_test_clients(sdev); +} + /* baytrail ops */ const struct snd_sof_dsp_ops sof_byt_ops = { /* device init */ @@ -879,6 +890,10 @@ const struct snd_sof_dsp_ops sof_byt_ops = { .suspend = byt_suspend, .resume = byt_resume, + /* client ops */ + .register_clients = byt_register_clients, + .unregister_clients = byt_unregister_clients, + /* DAI drivers */ .drv = byt_dai, .num_drv = 3, /* we have only 3 SSPs on byt*/ @@ -958,6 +973,10 @@ const struct snd_sof_dsp_ops sof_cht_ops = { .suspend = byt_suspend, .resume = byt_resume, + /* client ops */ + .register_clients = byt_register_clients, + .unregister_clients = byt_unregister_clients, + /* DAI drivers */ .drv = byt_dai, /* all 6 SSPs may be available for cherrytrail */ @@ -985,3 +1004,4 @@ EXPORT_SYMBOL_NS(cht_chip_info, SND_SOC_SOF_BAYTRAIL); MODULE_LICENSE("Dual BSD/GPL"); MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HIFI_EP_IPC); MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA); +MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_CLIENT); diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index a5d3258104c0..20afb622c315 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -19,6 +19,7 @@ #include "hda.h" #include "hda-ipc.h" #include "../sof-audio.h" +#include "intel-client.h" static const struct snd_sof_debugfs_map cnl_dsp_debugfs[] = { {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS}, @@ -230,6 +231,16 @@ void cnl_ipc_dump(struct snd_sof_dev *sdev) hipcida, hipctdr, hipcctl); } +static int cnl_register_clients(struct snd_sof_dev *sdev) +{ + return intel_register_ipc_test_clients(sdev); +} + +static void cnl_unregister_clients(struct snd_sof_dev *sdev) +{ + intel_unregister_ipc_test_clients(sdev); +} + /* cannonlake ops */ const struct snd_sof_dsp_ops sof_cnl_ops = { /* probe and remove */ @@ -306,6 +317,10 @@ const struct snd_sof_dsp_ops sof_cnl_ops = { .trace_release = hda_dsp_trace_release, .trace_trigger = hda_dsp_trace_trigger, + /* client ops */ + .register_clients = cnl_register_clients, + .unregister_clients = cnl_unregister_clients, + /* DAI drivers */ .drv = skl_dai, .num_drv = SOF_SKL_NUM_DAIS, @@ -393,3 +408,4 @@ const struct sof_intel_dsp_desc jsl_chip_info = { .ssp_base_offset = CNL_SSP_BASE_OFFSET, }; EXPORT_SYMBOL_NS(jsl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); +MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_CLIENT); diff --git a/sound/soc/sof/intel/intel-client.c b/sound/soc/sof/intel/intel-client.c new file mode 100644 index 000000000000..a612de365fc5 --- /dev/null +++ b/sound/soc/sof/intel/intel-client.c @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan +// + +#include +#include "../sof-priv.h" +#include "../sof-client.h" +#include "intel-client.h" + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST_CLIENT) +int intel_register_ipc_test_clients(struct snd_sof_dev *sdev) +{ + int ret; + + /* + * Register 2 IPC clients to facilitate tandem flood test. The device name below is + * appended with the device ID assigned automatically when the auxiliary device is + * registered making them unique. + */ + ret = sof_client_dev_register(sdev, "ipc_test", 0); + if (ret < 0) + return ret; + + return sof_client_dev_register(sdev, "ipc_test", 1); +} +EXPORT_SYMBOL_NS_GPL(intel_register_ipc_test_clients, SND_SOC_SOF_INTEL_CLIENT); + +void intel_unregister_ipc_test_clients(struct snd_sof_dev *sdev) +{ + sof_client_dev_unregister(sdev, "ipc_test", 0); + sof_client_dev_unregister(sdev, "ipc_test", 1); +} +EXPORT_SYMBOL_NS_GPL(intel_unregister_ipc_test_clients, SND_SOC_SOF_INTEL_CLIENT); +#endif + +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT); diff --git a/sound/soc/sof/intel/intel-client.h b/sound/soc/sof/intel/intel-client.h new file mode 100644 index 000000000000..49b2c6c0dcc4 --- /dev/null +++ b/sound/soc/sof/intel/intel-client.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Ranjani Sridharan + */ + +#ifndef __INTEL_CLIENT_H +#define __INTEL_CLIENT_H + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST_CLIENT) +int intel_register_ipc_test_clients(struct snd_sof_dev *sdev); +void intel_unregister_ipc_test_clients(struct snd_sof_dev *sdev); +#else +static inline int intel_register_ipc_test_clients(struct snd_sof_dev *sdev) +{ + return 0; +} + +static void intel_unregister_ipc_test_clients(struct snd_sof_dev *sdev) {} +#endif + +#endif From patchwork Fri Oct 23 00:33:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Ertman X-Patchwork-Id: 11852161 X-Patchwork-Delegate: kuba@kernel.org 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=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, 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 315D5C55179 for ; Fri, 23 Oct 2020 00:36:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D3A09223C7 for ; Fri, 23 Oct 2020 00:36:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S373989AbgJWAgT (ORCPT ); Thu, 22 Oct 2020 20:36:19 -0400 Received: from mga11.intel.com ([192.55.52.93]:43016 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S373791AbgJWAf3 (ORCPT ); Thu, 22 Oct 2020 20:35:29 -0400 IronPort-SDR: 4GQUuxDWy9cAeqppVlIQtafA3HDfHvgri3duOEs/8Acw5sJg43D3CKMBUK8FmA5PxwnMXamAj8 YQ6qMkY2jOUg== X-IronPort-AV: E=McAfee;i="6000,8403,9782"; a="164118647" X-IronPort-AV: E=Sophos;i="5.77,404,1596524400"; d="scan'208";a="164118647" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Oct 2020 17:35:26 -0700 IronPort-SDR: 6Pptt0QEJl+6NDAsOUm3bC0SzSV690gnyVhTidKs6s1Oo0y5OX+ZNJ4Igk7sUUdjBJUGQD7UVP IVJvuOyZIHGw== X-IronPort-AV: E=Sophos;i="5.77,404,1596524400"; d="scan'208";a="302505814" Received: from dmert-dev.jf.intel.com ([10.166.241.5]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Oct 2020 17:35:26 -0700 From: Dave Ertman To: alsa-devel@alsa-project.org Cc: tiwai@suse.de, broonie@kernel.org, linux-rdma@vger.kernel.org, jgg@nvidia.com, dledford@redhat.com, netdev@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, gregkh@linuxfoundation.org, ranjani.sridharan@linux.intel.com, pierre-louis.bossart@linux.intel.com, fred.oh@linux.intel.com, parav@mellanox.com, shiraz.saleem@intel.com, dan.j.williams@intel.com, kiran.patil@intel.com, linux-kernel@vger.kernel.org, leonro@nvidia.com Subject: [PATCH v3 06/10] ASoC: SOF: Intel: Remove IPC flood test support in SOF core Date: Thu, 22 Oct 2020 17:33:34 -0700 Message-Id: <20201023003338.1285642-7-david.m.ertman@intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201023003338.1285642-1-david.m.ertman@intel.com> References: <20201023003338.1285642-1-david.m.ertman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Ranjani Sridharan Remove the IPC flood test support in the SOF core as it is now added in the IPC flood test client. Reviewed-by: Pierre-Louis Bossart Signed-off-by: Fred Oh Signed-off-by: Ranjani Sridharan Signed-off-by: Dave Ertman --- sound/soc/sof/Kconfig | 8 -- sound/soc/sof/debug.c | 230 --------------------------------------- sound/soc/sof/sof-priv.h | 6 +- 3 files changed, 1 insertion(+), 243 deletions(-) diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index 13bde36cc5d7..a0f9474b8143 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -182,14 +182,6 @@ config SND_SOC_SOF_DEBUG_ENABLE_FIRMWARE_TRACE module parameter (similar to dynamic debug) If unsure, select "N". -config SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST - bool "SOF enable IPC flood test" - help - This option enables the IPC flood test which can be used to flood - the DSP with test IPCs and gather stats about response times. - Say Y if you want to enable IPC flood test. - If unsure, select "N". - config SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST_CLIENT tristate "SOF enable IPC flood test client" depends on SND_SOC_SOF_CLIENT diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index 9419a99bab53..d224641768da 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -232,120 +232,10 @@ static int snd_sof_debugfs_probe_item(struct snd_sof_dev *sdev, } #endif -#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) -#define MAX_IPC_FLOOD_DURATION_MS 1000 -#define MAX_IPC_FLOOD_COUNT 10000 -#define IPC_FLOOD_TEST_RESULT_LEN 512 - -static int sof_debug_ipc_flood_test(struct snd_sof_dev *sdev, - struct snd_sof_dfsentry *dfse, - bool flood_duration_test, - unsigned long ipc_duration_ms, - unsigned long ipc_count) -{ - struct sof_ipc_cmd_hdr hdr; - struct sof_ipc_reply reply; - u64 min_response_time = U64_MAX; - ktime_t start, end, test_end; - u64 avg_response_time = 0; - u64 max_response_time = 0; - u64 ipc_response_time; - int i = 0; - int ret; - - /* configure test IPC */ - hdr.cmd = SOF_IPC_GLB_TEST_MSG | SOF_IPC_TEST_IPC_FLOOD; - hdr.size = sizeof(hdr); - - /* set test end time for duration flood test */ - if (flood_duration_test) - test_end = ktime_get_ns() + ipc_duration_ms * NSEC_PER_MSEC; - - /* send test IPC's */ - while (1) { - start = ktime_get(); - ret = sof_ipc_tx_message(sdev->ipc, hdr.cmd, &hdr, hdr.size, - &reply, sizeof(reply)); - end = ktime_get(); - - if (ret < 0) - break; - - /* compute min and max response times */ - ipc_response_time = ktime_to_ns(ktime_sub(end, start)); - min_response_time = min(min_response_time, ipc_response_time); - max_response_time = max(max_response_time, ipc_response_time); - - /* sum up response times */ - avg_response_time += ipc_response_time; - i++; - - /* test complete? */ - if (flood_duration_test) { - if (ktime_to_ns(end) >= test_end) - break; - } else { - if (i == ipc_count) - break; - } - } - - if (ret < 0) - dev_err(sdev->dev, - "error: ipc flood test failed at %d iterations\n", i); - - /* return if the first IPC fails */ - if (!i) - return ret; - - /* compute average response time */ - do_div(avg_response_time, i); - - /* clear previous test output */ - memset(dfse->cache_buf, 0, IPC_FLOOD_TEST_RESULT_LEN); - - if (flood_duration_test) { - dev_dbg(sdev->dev, "IPC Flood test duration: %lums\n", - ipc_duration_ms); - snprintf(dfse->cache_buf, IPC_FLOOD_TEST_RESULT_LEN, - "IPC Flood test duration: %lums\n", ipc_duration_ms); - } - - dev_dbg(sdev->dev, - "IPC Flood count: %d, Avg response time: %lluns\n", - i, avg_response_time); - dev_dbg(sdev->dev, "Max response time: %lluns\n", - max_response_time); - dev_dbg(sdev->dev, "Min response time: %lluns\n", - min_response_time); - - /* format output string */ - snprintf(dfse->cache_buf + strlen(dfse->cache_buf), - IPC_FLOOD_TEST_RESULT_LEN - strlen(dfse->cache_buf), - "IPC Flood count: %d\nAvg response time: %lluns\n", - i, avg_response_time); - - snprintf(dfse->cache_buf + strlen(dfse->cache_buf), - IPC_FLOOD_TEST_RESULT_LEN - strlen(dfse->cache_buf), - "Max response time: %lluns\nMin response time: %lluns\n", - max_response_time, min_response_time); - - return ret; -} -#endif static ssize_t sof_dfsentry_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { -#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) - struct snd_sof_dfsentry *dfse = file->private_data; - struct snd_sof_dev *sdev = dfse->sdev; - unsigned long ipc_duration_ms = 0; - bool flood_duration_test = false; - unsigned long ipc_count = 0; - struct dentry *dentry; - int err; -#endif size_t size; char *string; int ret; @@ -357,78 +247,6 @@ static ssize_t sof_dfsentry_write(struct file *file, const char __user *buffer, size = simple_write_to_buffer(string, count, ppos, buffer, count); ret = size; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) - /* - * write op is only supported for ipc_flood_count or - * ipc_flood_duration_ms debugfs entries atm. - * ipc_flood_count floods the DSP with the number of IPC's specified. - * ipc_duration_ms test floods the DSP for the time specified - * in the debugfs entry. - */ - dentry = file->f_path.dentry; - if (strcmp(dentry->d_name.name, "ipc_flood_count") && - strcmp(dentry->d_name.name, "ipc_flood_duration_ms")) { - ret = -EINVAL; - goto out; - } - - if (!strcmp(dentry->d_name.name, "ipc_flood_duration_ms")) - flood_duration_test = true; - - /* test completion criterion */ - if (flood_duration_test) - ret = kstrtoul(string, 0, &ipc_duration_ms); - else - ret = kstrtoul(string, 0, &ipc_count); - if (ret < 0) - goto out; - - /* limit max duration/ipc count for flood test */ - if (flood_duration_test) { - if (!ipc_duration_ms) { - ret = size; - goto out; - } - - /* find the minimum. min() is not used to avoid warnings */ - if (ipc_duration_ms > MAX_IPC_FLOOD_DURATION_MS) - ipc_duration_ms = MAX_IPC_FLOOD_DURATION_MS; - } else { - if (!ipc_count) { - ret = size; - goto out; - } - - /* find the minimum. min() is not used to avoid warnings */ - if (ipc_count > MAX_IPC_FLOOD_COUNT) - ipc_count = MAX_IPC_FLOOD_COUNT; - } - - ret = pm_runtime_get_sync(sdev->dev); - if (ret < 0 && ret != -EACCES) { - dev_err_ratelimited(sdev->dev, - "error: debugfs write failed to resume %d\n", - ret); - pm_runtime_put_noidle(sdev->dev); - goto out; - } - - /* flood test */ - ret = sof_debug_ipc_flood_test(sdev, dfse, flood_duration_test, - ipc_duration_ms, ipc_count); - - pm_runtime_mark_last_busy(sdev->dev); - err = pm_runtime_put_autosuspend(sdev->dev); - if (err < 0) - dev_err_ratelimited(sdev->dev, - "error: debugfs write failed to idle %d\n", - err); - - /* return size if test is successful */ - if (ret >= 0) - ret = size; -out: -#endif kfree(string); return ret; } @@ -444,25 +262,6 @@ static ssize_t sof_dfsentry_read(struct file *file, char __user *buffer, int size; u8 *buf; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) - struct dentry *dentry; - - dentry = file->f_path.dentry; - if ((!strcmp(dentry->d_name.name, "ipc_flood_count") || - !strcmp(dentry->d_name.name, "ipc_flood_duration_ms")) && - dfse->cache_buf) { - if (*ppos) - return 0; - - count = strlen(dfse->cache_buf); - size_ret = copy_to_user(buffer, dfse->cache_buf, count); - if (size_ret) - return -EFAULT; - - *ppos += count; - return count; - } -#endif size = dfse->size; /* validate position & count */ @@ -606,17 +405,6 @@ int snd_sof_debugfs_buf_item(struct snd_sof_dev *sdev, dfse->size = size; dfse->sdev = sdev; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) - /* - * cache_buf is unused for SOF_DFSENTRY_TYPE_BUF debugfs entries. - * So, use it to save the results of the last IPC flood test. - */ - dfse->cache_buf = devm_kzalloc(sdev->dev, IPC_FLOOD_TEST_RESULT_LEN, - GFP_KERNEL); - if (!dfse->cache_buf) - return -ENOMEM; -#endif - debugfs_create_file(name, mode, sdev->debugfs_root, dfse, &sof_dfs_fops); /* add to dfsentry list */ @@ -662,24 +450,6 @@ int snd_sof_dbg_init(struct snd_sof_dev *sdev) return err; #endif -#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) - /* create read-write ipc_flood_count debugfs entry */ - err = snd_sof_debugfs_buf_item(sdev, NULL, 0, - "ipc_flood_count", 0666); - - /* errors are only due to memory allocation, not debugfs */ - if (err < 0) - return err; - - /* create read-write ipc_flood_duration_ms debugfs entry */ - err = snd_sof_debugfs_buf_item(sdev, NULL, 0, - "ipc_flood_duration_ms", 0666); - - /* errors are only due to memory allocation, not debugfs */ - if (err < 0) - return err; -#endif - return 0; } EXPORT_SYMBOL_GPL(snd_sof_dbg_init); diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index cca239c09d0e..e44158410b24 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -50,10 +50,6 @@ extern int sof_core_debug; #define SOF_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_FLOAT) -#define ENABLE_DEBUGFS_CACHEBUF \ - (IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) || \ - IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST)) - /* So far the primary core on all DSPs has ID 0 */ #define SOF_DSP_PRIMARY_CORE 0 @@ -301,7 +297,7 @@ struct snd_sof_dfsentry { * or if it is accessible only when the DSP is in D0. */ enum sof_debugfs_access_type access_type; -#if ENABLE_DEBUGFS_CACHEBUF +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) char *cache_buf; /* buffer to cache the contents of debugfs memory */ #endif struct snd_sof_dev *sdev; From patchwork Fri Oct 23 00:33:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Ertman X-Patchwork-Id: 11852121 X-Patchwork-Delegate: kuba@kernel.org 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=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, 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 EF3E5C388F9 for ; Fri, 23 Oct 2020 00:35:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9AC24223C7 for ; Fri, 23 Oct 2020 00:35:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S373910AbgJWAff (ORCPT ); Thu, 22 Oct 2020 20:35:35 -0400 Received: from mga11.intel.com ([192.55.52.93]:43018 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S373855AbgJWAfa (ORCPT ); Thu, 22 Oct 2020 20:35:30 -0400 IronPort-SDR: rfQdzNuwdYgwltS9QZkTBOv7Wp4bLJZstBs/gAFhywXgQbfG80WnDUW3Fb6C4xPmloH4JXmEt1 mHS9eOa5JNqg== X-IronPort-AV: E=McAfee;i="6000,8403,9782"; a="164118649" X-IronPort-AV: E=Sophos;i="5.77,404,1596524400"; d="scan'208";a="164118649" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Oct 2020 17:35:27 -0700 IronPort-SDR: i7OEA259GyUOowfHePBXVGXg7D8v4EvdiKvZDDeFM1HCojofUBOP9qDO9exRdoVIqiOSHj57M/ yRuuNOmljpgw== X-IronPort-AV: E=Sophos;i="5.77,404,1596524400"; d="scan'208";a="302505820" Received: from dmert-dev.jf.intel.com ([10.166.241.5]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Oct 2020 17:35:26 -0700 From: Dave Ertman To: alsa-devel@alsa-project.org Cc: tiwai@suse.de, broonie@kernel.org, linux-rdma@vger.kernel.org, jgg@nvidia.com, dledford@redhat.com, netdev@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, gregkh@linuxfoundation.org, ranjani.sridharan@linux.intel.com, pierre-louis.bossart@linux.intel.com, fred.oh@linux.intel.com, parav@mellanox.com, shiraz.saleem@intel.com, dan.j.williams@intel.com, kiran.patil@intel.com, linux-kernel@vger.kernel.org, leonro@nvidia.com Subject: [PATCH v3 07/10] ASoC: SOF: sof-client: Add client APIs to access probes ops Date: Thu, 22 Oct 2020 17:33:35 -0700 Message-Id: <20201023003338.1285642-8-david.m.ertman@intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201023003338.1285642-1-david.m.ertman@intel.com> References: <20201023003338.1285642-1-david.m.ertman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Ranjani Sridharan Add client APIs to invoke the platform-specific DSP probes ops. Also, add a new API to get the SOF core device pointer which will be used for DMA buffer allocation. Reviewed-by: Pierre-Louis Bossart Tested-by: Fred Oh Signed-off-by: Ranjani Sridharan Signed-off-by: Dave Ertman --- sound/soc/sof/sof-client.c | 55 ++++++++++++++++++++++++++++++++++++++ sound/soc/sof/sof-client.h | 25 +++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/sound/soc/sof/sof-client.c b/sound/soc/sof/sof-client.c index dd75a0ba4c28..838aaa5ea179 100644 --- a/sound/soc/sof/sof-client.c +++ b/sound/soc/sof/sof-client.c @@ -11,6 +11,7 @@ #include #include #include +#include "ops.h" #include "sof-client.h" #include "sof-priv.h" @@ -112,4 +113,58 @@ struct dentry *sof_client_get_debugfs_root(struct sof_client_dev *cdev) } EXPORT_SYMBOL_NS_GPL(sof_client_get_debugfs_root, SND_SOC_SOF_CLIENT); +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES_CLIENT) +int sof_client_probe_compr_assign(struct sof_client_dev *cdev, + struct snd_compr_stream *cstream, + struct snd_soc_dai *dai) +{ + return snd_sof_probe_compr_assign(cdev->sdev, cstream, dai); +} +EXPORT_SYMBOL_NS_GPL(sof_client_probe_compr_assign, SND_SOC_SOF_CLIENT); + +int sof_client_probe_compr_free(struct sof_client_dev *cdev, + struct snd_compr_stream *cstream, + struct snd_soc_dai *dai) +{ + return snd_sof_probe_compr_free(cdev->sdev, cstream, dai); +} +EXPORT_SYMBOL_NS_GPL(sof_client_probe_compr_free, SND_SOC_SOF_CLIENT); + +int sof_client_probe_compr_set_params(struct sof_client_dev *cdev, + struct snd_compr_stream *cstream, + struct snd_compr_params *params, + struct snd_soc_dai *dai) +{ + return snd_sof_probe_compr_set_params(cdev->sdev, cstream, params, dai); +} +EXPORT_SYMBOL_NS_GPL(sof_client_probe_compr_set_params, SND_SOC_SOF_CLIENT); + +int sof_client_probe_compr_trigger(struct sof_client_dev *cdev, + struct snd_compr_stream *cstream, int cmd, + struct snd_soc_dai *dai) +{ + return snd_sof_probe_compr_trigger(cdev->sdev, cstream, cmd, dai); +} +EXPORT_SYMBOL_NS_GPL(sof_client_probe_compr_trigger, SND_SOC_SOF_CLIENT); + +int sof_client_probe_compr_pointer(struct sof_client_dev *cdev, + struct snd_compr_stream *cstream, + struct snd_compr_tstamp *tstamp, + struct snd_soc_dai *dai) +{ + return snd_sof_probe_compr_pointer(cdev->sdev, cstream, tstamp, dai); +} +EXPORT_SYMBOL_NS_GPL(sof_client_probe_compr_pointer, SND_SOC_SOF_CLIENT); +#endif + +/* + * DMA buffer alloc fails when using the client device. Use the SOF core device instead. + * This will be needed for clients other than the probes client device as well. + */ +struct device *sof_client_get_dma_dev(struct sof_client_dev *cdev) +{ + return cdev->sdev->dev; +} +EXPORT_SYMBOL_NS_GPL(sof_client_get_dma_dev, SND_SOC_SOF_CLIENT); + MODULE_LICENSE("GPL"); diff --git a/sound/soc/sof/sof-client.h b/sound/soc/sof/sof-client.h index 429282df9f65..be80053068c9 100644 --- a/sound/soc/sof/sof-client.h +++ b/sound/soc/sof/sof-client.h @@ -7,6 +7,10 @@ #include #include #include +#include +#include +#include +#include #define SOF_CLIENT_PROBE_TIMEOUT_MS 2000 @@ -50,6 +54,27 @@ int sof_client_ipc_tx_message(struct sof_client_dev *cdev, u32 header, void *msg size_t msg_bytes, void *reply_data, size_t reply_bytes); struct dentry *sof_client_get_debugfs_root(struct sof_client_dev *cdev); +struct device *sof_client_get_dma_dev(struct sof_client_dev *cdev); + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES_CLIENT) +int sof_client_probe_compr_assign(struct sof_client_dev *cdev, + struct snd_compr_stream *cstream, + struct snd_soc_dai *dai); +int sof_client_probe_compr_free(struct sof_client_dev *cdev, + struct snd_compr_stream *cstream, + struct snd_soc_dai *dai); +int sof_client_probe_compr_set_params(struct sof_client_dev *cdev, + struct snd_compr_stream *cstream, + struct snd_compr_params *params, + struct snd_soc_dai *dai); +int sof_client_probe_compr_trigger(struct sof_client_dev *cdev, + struct snd_compr_stream *cstream, int cmd, + struct snd_soc_dai *dai); +int sof_client_probe_compr_pointer(struct sof_client_dev *cdev, + struct snd_compr_stream *cstream, + struct snd_compr_tstamp *tstamp, + struct snd_soc_dai *dai); +#endif /** * module_sof_client_driver() - Helper macro for registering an SOF Client From patchwork Fri Oct 23 00:33:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Ertman X-Patchwork-Id: 11852157 X-Patchwork-Delegate: kuba@kernel.org 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=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, 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 58123C63697 for ; Fri, 23 Oct 2020 00:36:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0F04824631 for ; Fri, 23 Oct 2020 00:36:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S373975AbgJWAgM (ORCPT ); Thu, 22 Oct 2020 20:36:12 -0400 Received: from mga11.intel.com ([192.55.52.93]:43009 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S373861AbgJWAfa (ORCPT ); Thu, 22 Oct 2020 20:35:30 -0400 IronPort-SDR: EQOVrewm/EdYCG7GEFQj6QkZvgZl7GE1c6/1Q6GntpjCUOE6lyTxxzyotWOihoG9RNeZSL7uDP MaNsXUeALieA== X-IronPort-AV: E=McAfee;i="6000,8403,9782"; a="164118651" X-IronPort-AV: E=Sophos;i="5.77,404,1596524400"; d="scan'208";a="164118651" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Oct 2020 17:35:27 -0700 IronPort-SDR: 18qW83gLRKyW77TzyKGUMM+iMckw6+8PkfCBvA9H1uWBMqZ6cl4vtWcGGDzKgnZ4+lHtmCbdLo ekgwrk0PTh+Q== X-IronPort-AV: E=Sophos;i="5.77,404,1596524400"; d="scan'208";a="302505825" Received: from dmert-dev.jf.intel.com ([10.166.241.5]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Oct 2020 17:35:27 -0700 From: Dave Ertman To: alsa-devel@alsa-project.org Cc: tiwai@suse.de, broonie@kernel.org, linux-rdma@vger.kernel.org, jgg@nvidia.com, dledford@redhat.com, netdev@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, gregkh@linuxfoundation.org, ranjani.sridharan@linux.intel.com, pierre-louis.bossart@linux.intel.com, fred.oh@linux.intel.com, parav@mellanox.com, shiraz.saleem@intel.com, dan.j.williams@intel.com, kiran.patil@intel.com, linux-kernel@vger.kernel.org, leonro@nvidia.com Subject: [PATCH v3 08/10] ASoC: SOF: compress: move and export sof_probe_compr_ops Date: Thu, 22 Oct 2020 17:33:36 -0700 Message-Id: <20201023003338.1285642-9-david.m.ertman@intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201023003338.1285642-1-david.m.ertman@intel.com> References: <20201023003338.1285642-1-david.m.ertman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Ranjani Sridharan sof_probe_compr_ops are not platform-specific. So move it to common compress code and export the symbol. The compilation of the common compress code is already dependent on the selection of CONFIG_SND_SOC_SOF_DEBUG_PROBES, so no need to check the Kconfig section for defining sof_probe_compr_ops again. Reviewed-by: Pierre-Louis Bossart Tested-by: Fred Oh Signed-off-by: Ranjani Sridharan Signed-off-by: Dave Ertman --- sound/soc/sof/compress.c | 9 +++++++++ sound/soc/sof/compress.h | 1 + sound/soc/sof/intel/hda-dai.c | 12 ------------ 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/sound/soc/sof/compress.c b/sound/soc/sof/compress.c index 2d4969c705a4..0443f171b4e7 100644 --- a/sound/soc/sof/compress.c +++ b/sound/soc/sof/compress.c @@ -13,6 +13,15 @@ #include "ops.h" #include "probe.h" +struct snd_soc_cdai_ops sof_probe_compr_ops = { + .startup = sof_probe_compr_open, + .shutdown = sof_probe_compr_free, + .set_params = sof_probe_compr_set_params, + .trigger = sof_probe_compr_trigger, + .pointer = sof_probe_compr_pointer, +}; +EXPORT_SYMBOL(sof_probe_compr_ops); + struct snd_compress_ops sof_probe_compressed_ops = { .copy = sof_probe_compr_copy, }; diff --git a/sound/soc/sof/compress.h b/sound/soc/sof/compress.h index ca8790bd4b13..689c83ac8ffc 100644 --- a/sound/soc/sof/compress.h +++ b/sound/soc/sof/compress.h @@ -13,6 +13,7 @@ #include +extern struct snd_soc_cdai_ops sof_probe_compr_ops; extern struct snd_compress_ops sof_probe_compressed_ops; int sof_probe_compr_open(struct snd_compr_stream *cstream, diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index c6cb8c212eca..1acec1176986 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -400,18 +400,6 @@ static const struct snd_soc_dai_ops hda_link_dai_ops = { .prepare = hda_link_pcm_prepare, }; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_PROBES) -#include "../compress.h" - -static struct snd_soc_cdai_ops sof_probe_compr_ops = { - .startup = sof_probe_compr_open, - .shutdown = sof_probe_compr_free, - .set_params = sof_probe_compr_set_params, - .trigger = sof_probe_compr_trigger, - .pointer = sof_probe_compr_pointer, -}; - -#endif #endif /* From patchwork Fri Oct 23 00:33:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Ertman X-Patchwork-Id: 11852149 X-Patchwork-Delegate: kuba@kernel.org 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=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, 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 E4797C388F7 for ; Fri, 23 Oct 2020 00:36:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8E16C223C7 for ; Fri, 23 Oct 2020 00:36:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S373955AbgJWAf7 (ORCPT ); Thu, 22 Oct 2020 20:35:59 -0400 Received: from mga11.intel.com ([192.55.52.93]:43016 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S373862AbgJWAfb (ORCPT ); Thu, 22 Oct 2020 20:35:31 -0400 IronPort-SDR: 9Ox4hKuLhlgFZgxEfz5rp76Q3+RDylzSEVtK0wdgl6xGMV8FCJvl93pJV5TBMmSzz+CbTrNCku Z7m/55rJqMlQ== X-IronPort-AV: E=McAfee;i="6000,8403,9782"; a="164118653" X-IronPort-AV: E=Sophos;i="5.77,404,1596524400"; d="scan'208";a="164118653" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Oct 2020 17:35:28 -0700 IronPort-SDR: VSIfz1C6L6unviDf3OrECj31cEv41E3CgzAucLfV01Gq3uo9WopyxYHWBtgP2wC7PNWK/Lip4o TGxBIhtXlFGQ== X-IronPort-AV: E=Sophos;i="5.77,404,1596524400"; d="scan'208";a="302505831" Received: from dmert-dev.jf.intel.com ([10.166.241.5]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Oct 2020 17:35:27 -0700 From: Dave Ertman To: alsa-devel@alsa-project.org Cc: tiwai@suse.de, broonie@kernel.org, linux-rdma@vger.kernel.org, jgg@nvidia.com, dledford@redhat.com, netdev@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, gregkh@linuxfoundation.org, ranjani.sridharan@linux.intel.com, pierre-louis.bossart@linux.intel.com, fred.oh@linux.intel.com, parav@mellanox.com, shiraz.saleem@intel.com, dan.j.williams@intel.com, kiran.patil@intel.com, linux-kernel@vger.kernel.org, leonro@nvidia.com Subject: [PATCH v3 09/10] ASoC: SOF: Add new client driver for probes support Date: Thu, 22 Oct 2020 17:33:37 -0700 Message-Id: <20201023003338.1285642-10-david.m.ertman@intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201023003338.1285642-1-david.m.ertman@intel.com> References: <20201023003338.1285642-1-david.m.ertman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Ranjani Sridharan Add a new client driver for probes support and move all the probes-related code from the core to the client driver. The probes client driver registers a component driver with one CPU DAI driver for extraction and creates a new sound card with one DUMMY DAI link with a dummy codec that will be used for extracting audio data from specific points in the audio pipeline. The probes debugfs ops are based on the initial implementation by Cezary Rojewski and have been moved out of the SOF core into the client driver making it easier to maintain. This change will make it easier for the probes functionality to be added for all platforms without having the need to modify the existing(15+) machine drivers. Reviewed-by: Pierre-Louis Bossart Tested-by: Fred Oh Signed-off-by: Ranjani Sridharan Signed-off-by: Dave Ertman --- sound/soc/sof/Kconfig | 18 +- sound/soc/sof/Makefile | 3 +- sound/soc/sof/compress.c | 51 ++-- sound/soc/sof/core.c | 6 - sound/soc/sof/debug.c | 227 ---------------- sound/soc/sof/intel/hda-dai.c | 15 -- sound/soc/sof/intel/hda.h | 6 - sound/soc/sof/pcm.c | 11 - sound/soc/sof/probe.c | 124 ++++----- sound/soc/sof/probe.h | 41 +-- sound/soc/sof/sof-priv.h | 4 - sound/soc/sof/sof-probes-client.c | 414 ++++++++++++++++++++++++++++++ 12 files changed, 545 insertions(+), 375 deletions(-) create mode 100644 sound/soc/sof/sof-probes-client.c diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index a0f9474b8143..9fa00780c842 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -42,13 +42,11 @@ config SND_SOC_SOF_OF Say Y if you need this option. If unsure select "N". config SND_SOC_SOF_DEBUG_PROBES - bool "SOF enable data probing" + bool select SND_SOC_COMPRESS help - This option enables the data probing feature that can be used to - gather data directly from specific points of the audio pipeline. - Say Y if you want to enable probes. - If unsure, select "N". + This option is not user-selectable but automagically handled by + 'select' statements at a higher level. config SND_SOC_SOF_CLIENT tristate @@ -192,6 +190,15 @@ config SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST_CLIENT Say Y if you want to enable IPC flood test. If unsure, select "N". +config SND_SOC_SOF_DEBUG_PROBES_CLIENT + tristate "SOF enable data probing" + depends on SND_SOC_SOF_CLIENT + help + This option enables the data probing feature that can be used to + gather data directly from specific points of the audio pipeline. + Say Y if you want to enable probes. + If unsure, select "N". + config SND_SOC_SOF_DEBUG_RETAIN_DSP_CONTEXT bool "SOF retain DSP context on any FW exceptions" help @@ -207,6 +214,7 @@ endif ## SND_SOC_SOF_DEVELOPER_SUPPORT config SND_SOC_SOF tristate select SND_SOC_SOF_CLIENT if SND_SOC_SOF_CLIENT_SUPPORT + select SND_SOC_SOF_DEBUG_PROBES if SND_SOC_SOF_DEBUG_PROBES_CLIENT select SND_SOC_TOPOLOGY select SND_SOC_SOF_NOCODEC if SND_SOC_SOF_NOCODEC_SUPPORT help diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile index baa93fe2cc9a..cf49466f7910 100644 --- a/sound/soc/sof/Makefile +++ b/sound/soc/sof/Makefile @@ -3,7 +3,7 @@ snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\ control.o trace.o utils.o sof-audio.o snd-sof-client-objs := sof-client.o -snd-sof-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES) += probe.o compress.o +snd-sof-probes-objs := probe.o compress.o sof-probes-client.o snd-sof-pci-objs := sof-pci-dev.o snd-sof-acpi-objs := sof-acpi-dev.o @@ -24,6 +24,7 @@ obj-$(CONFIG_SND_SOC_SOF_PCI) += snd-sof-pci.o obj-$(CONFIG_SND_SOC_SOF_CLIENT) += snd-sof-client.o obj-$(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST_CLIENT) += snd-sof-ipc-test.o +obj-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES_CLIENT) += snd-sof-probes.o obj-$(CONFIG_SND_SOC_SOF_INTEL_TOPLEVEL) += intel/ obj-$(CONFIG_SND_SOC_SOF_IMX_TOPLEVEL) += imx/ diff --git a/sound/soc/sof/compress.c b/sound/soc/sof/compress.c index 0443f171b4e7..bbb77f028e74 100644 --- a/sound/soc/sof/compress.c +++ b/sound/soc/sof/compress.c @@ -10,8 +10,8 @@ #include #include "compress.h" -#include "ops.h" #include "probe.h" +#include "sof-client.h" struct snd_soc_cdai_ops sof_probe_compr_ops = { .startup = sof_probe_compr_open, @@ -30,17 +30,18 @@ EXPORT_SYMBOL(sof_probe_compressed_ops); int sof_probe_compr_open(struct snd_compr_stream *cstream, struct snd_soc_dai *dai) { - struct snd_sof_dev *sdev = - snd_soc_component_get_drvdata(dai->component); + struct snd_soc_card *card = snd_soc_component_get_drvdata(dai->component); + struct sof_client_dev *cdev = snd_soc_card_get_drvdata(card); + struct sof_probes_data *probes_data = cdev->data; int ret; - ret = snd_sof_probe_compr_assign(sdev, cstream, dai); + ret = sof_client_probe_compr_assign(cdev, cstream, dai); if (ret < 0) { dev_err(dai->dev, "Failed to assign probe stream: %d\n", ret); return ret; } - sdev->extractor_stream_tag = ret; + probes_data->extractor_stream_tag = ret; return 0; } EXPORT_SYMBOL(sof_probe_compr_open); @@ -48,55 +49,57 @@ EXPORT_SYMBOL(sof_probe_compr_open); int sof_probe_compr_free(struct snd_compr_stream *cstream, struct snd_soc_dai *dai) { - struct snd_sof_dev *sdev = - snd_soc_component_get_drvdata(dai->component); + struct snd_soc_card *card = snd_soc_component_get_drvdata(dai->component); + struct sof_client_dev *cdev = snd_soc_card_get_drvdata(card); + struct sof_probes_data *probes_data = cdev->data; struct sof_probe_point_desc *desc; size_t num_desc; int i, ret; /* disconnect all probe points */ - ret = sof_ipc_probe_points_info(sdev, &desc, &num_desc); + ret = sof_probe_points_info(cdev, &desc, &num_desc); if (ret < 0) { dev_err(dai->dev, "Failed to get probe points: %d\n", ret); goto exit; } for (i = 0; i < num_desc; i++) - sof_ipc_probe_points_remove(sdev, &desc[i].buffer_id, 1); + sof_probe_points_remove(cdev, &desc[i].buffer_id, 1); kfree(desc); exit: - ret = sof_ipc_probe_deinit(sdev); + ret = sof_probe_deinit(cdev); if (ret < 0) dev_err(dai->dev, "Failed to deinit probe: %d\n", ret); - sdev->extractor_stream_tag = SOF_PROBE_INVALID_NODE_ID; + probes_data->extractor_stream_tag = SOF_PROBE_INVALID_NODE_ID; snd_compr_free_pages(cstream); - return snd_sof_probe_compr_free(sdev, cstream, dai); + return sof_client_probe_compr_free(cdev, cstream, dai); } EXPORT_SYMBOL(sof_probe_compr_free); int sof_probe_compr_set_params(struct snd_compr_stream *cstream, struct snd_compr_params *params, struct snd_soc_dai *dai) { + struct snd_soc_card *card = snd_soc_component_get_drvdata(dai->component); + struct sof_client_dev *cdev = snd_soc_card_get_drvdata(card); + struct sof_probes_data *probes_data = cdev->data; struct snd_compr_runtime *rtd = cstream->runtime; - struct snd_sof_dev *sdev = - snd_soc_component_get_drvdata(dai->component); int ret; cstream->dma_buffer.dev.type = SNDRV_DMA_TYPE_DEV_SG; - cstream->dma_buffer.dev.dev = sdev->dev; + cstream->dma_buffer.dev.dev = sof_client_get_dma_dev(cdev); ret = snd_compr_malloc_pages(cstream, rtd->buffer_size); if (ret < 0) return ret; - ret = snd_sof_probe_compr_set_params(sdev, cstream, params, dai); + ret = sof_client_probe_compr_set_params(cdev, cstream, params, dai); if (ret < 0) return ret; - ret = sof_ipc_probe_init(sdev, sdev->extractor_stream_tag, - rtd->dma_bytes); + ret = sof_probe_init(cdev, probes_data->extractor_stream_tag, + rtd->dma_bytes); if (ret < 0) { dev_err(dai->dev, "Failed to init probe: %d\n", ret); return ret; @@ -109,20 +112,20 @@ EXPORT_SYMBOL(sof_probe_compr_set_params); int sof_probe_compr_trigger(struct snd_compr_stream *cstream, int cmd, struct snd_soc_dai *dai) { - struct snd_sof_dev *sdev = - snd_soc_component_get_drvdata(dai->component); + struct snd_soc_card *card = snd_soc_component_get_drvdata(dai->component); + struct sof_client_dev *cdev = snd_soc_card_get_drvdata(card); - return snd_sof_probe_compr_trigger(sdev, cstream, cmd, dai); + return sof_client_probe_compr_trigger(cdev, cstream, cmd, dai); } EXPORT_SYMBOL(sof_probe_compr_trigger); int sof_probe_compr_pointer(struct snd_compr_stream *cstream, struct snd_compr_tstamp *tstamp, struct snd_soc_dai *dai) { - struct snd_sof_dev *sdev = - snd_soc_component_get_drvdata(dai->component); + struct snd_soc_card *card = snd_soc_component_get_drvdata(dai->component); + struct sof_client_dev *cdev = snd_soc_card_get_drvdata(card); - return snd_sof_probe_compr_pointer(sdev, cstream, tstamp, dai); + return sof_client_probe_compr_pointer(cdev, cstream, tstamp, dai); } EXPORT_SYMBOL(sof_probe_compr_pointer); diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index ddb9a12d5aac..9b72317d6525 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -14,9 +14,6 @@ #include #include "sof-priv.h" #include "ops.h" -#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) -#include "probe.h" -#endif /* see SOF_DBG_ flags */ int sof_core_debug; @@ -305,9 +302,6 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) sdev->pdata = plat_data; sdev->first_boot = true; sdev->fw_state = SOF_FW_BOOT_NOT_STARTED; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) - sdev->extractor_stream_tag = SOF_PROBE_INVALID_NODE_ID; -#endif dev_set_drvdata(dev, sdev); /* check all mandatory ops */ diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index d224641768da..234ae704c001 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -17,222 +17,6 @@ #include "sof-priv.h" #include "ops.h" -#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) -#include "probe.h" - -/** - * strsplit_u32 - Split string into sequence of u32 tokens - * @buf: String to split into tokens. - * @delim: String containing delimiter characters. - * @tkns: Returned u32 sequence pointer. - * @num_tkns: Returned number of tokens obtained. - */ -static int -strsplit_u32(char **buf, const char *delim, u32 **tkns, size_t *num_tkns) -{ - char *s; - u32 *data, *tmp; - size_t count = 0; - size_t cap = 32; - int ret = 0; - - *tkns = NULL; - *num_tkns = 0; - data = kcalloc(cap, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - while ((s = strsep(buf, delim)) != NULL) { - ret = kstrtouint(s, 0, data + count); - if (ret) - goto exit; - if (++count >= cap) { - cap *= 2; - tmp = krealloc(data, cap * sizeof(*data), GFP_KERNEL); - if (!tmp) { - ret = -ENOMEM; - goto exit; - } - data = tmp; - } - } - - if (!count) - goto exit; - *tkns = kmemdup(data, count * sizeof(*data), GFP_KERNEL); - if (*tkns == NULL) { - ret = -ENOMEM; - goto exit; - } - *num_tkns = count; - -exit: - kfree(data); - return ret; -} - -static int tokenize_input(const char __user *from, size_t count, - loff_t *ppos, u32 **tkns, size_t *num_tkns) -{ - char *buf; - int ret; - - buf = kmalloc(count + 1, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - ret = simple_write_to_buffer(buf, count, ppos, from, count); - if (ret != count) { - ret = ret >= 0 ? -EIO : ret; - goto exit; - } - - buf[count] = '\0'; - ret = strsplit_u32((char **)&buf, ",", tkns, num_tkns); -exit: - kfree(buf); - return ret; -} - -static ssize_t probe_points_read(struct file *file, - char __user *to, size_t count, loff_t *ppos) -{ - struct snd_sof_dfsentry *dfse = file->private_data; - struct snd_sof_dev *sdev = dfse->sdev; - struct sof_probe_point_desc *desc; - size_t num_desc, len = 0; - char *buf; - int i, ret; - - if (sdev->extractor_stream_tag == SOF_PROBE_INVALID_NODE_ID) { - dev_warn(sdev->dev, "no extractor stream running\n"); - return -ENOENT; - } - - buf = kzalloc(PAGE_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - ret = sof_ipc_probe_points_info(sdev, &desc, &num_desc); - if (ret < 0) - goto exit; - - for (i = 0; i < num_desc; i++) { - ret = snprintf(buf + len, PAGE_SIZE - len, - "Id: %#010x Purpose: %d Node id: %#x\n", - desc[i].buffer_id, desc[i].purpose, desc[i].stream_tag); - if (ret < 0) - goto free_desc; - len += ret; - } - - ret = simple_read_from_buffer(to, count, ppos, buf, len); -free_desc: - kfree(desc); -exit: - kfree(buf); - return ret; -} - -static ssize_t probe_points_write(struct file *file, - const char __user *from, size_t count, loff_t *ppos) -{ - struct snd_sof_dfsentry *dfse = file->private_data; - struct snd_sof_dev *sdev = dfse->sdev; - struct sof_probe_point_desc *desc; - size_t num_tkns, bytes; - u32 *tkns; - int ret; - - if (sdev->extractor_stream_tag == SOF_PROBE_INVALID_NODE_ID) { - dev_warn(sdev->dev, "no extractor stream running\n"); - return -ENOENT; - } - - ret = tokenize_input(from, count, ppos, &tkns, &num_tkns); - if (ret < 0) - return ret; - bytes = sizeof(*tkns) * num_tkns; - if (!num_tkns || (bytes % sizeof(*desc))) { - ret = -EINVAL; - goto exit; - } - - desc = (struct sof_probe_point_desc *)tkns; - ret = sof_ipc_probe_points_add(sdev, - desc, bytes / sizeof(*desc)); - if (!ret) - ret = count; -exit: - kfree(tkns); - return ret; -} - -static const struct file_operations probe_points_fops = { - .open = simple_open, - .read = probe_points_read, - .write = probe_points_write, - .llseek = default_llseek, -}; - -static ssize_t probe_points_remove_write(struct file *file, - const char __user *from, size_t count, loff_t *ppos) -{ - struct snd_sof_dfsentry *dfse = file->private_data; - struct snd_sof_dev *sdev = dfse->sdev; - size_t num_tkns; - u32 *tkns; - int ret; - - if (sdev->extractor_stream_tag == SOF_PROBE_INVALID_NODE_ID) { - dev_warn(sdev->dev, "no extractor stream running\n"); - return -ENOENT; - } - - ret = tokenize_input(from, count, ppos, &tkns, &num_tkns); - if (ret < 0) - return ret; - if (!num_tkns) { - ret = -EINVAL; - goto exit; - } - - ret = sof_ipc_probe_points_remove(sdev, tkns, num_tkns); - if (!ret) - ret = count; -exit: - kfree(tkns); - return ret; -} - -static const struct file_operations probe_points_remove_fops = { - .open = simple_open, - .write = probe_points_remove_write, - .llseek = default_llseek, -}; - -static int snd_sof_debugfs_probe_item(struct snd_sof_dev *sdev, - const char *name, mode_t mode, - const struct file_operations *fops) -{ - struct snd_sof_dfsentry *dfse; - - dfse = devm_kzalloc(sdev->dev, sizeof(*dfse), GFP_KERNEL); - if (!dfse) - return -ENOMEM; - - dfse->type = SOF_DFSENTRY_TYPE_BUF; - dfse->sdev = sdev; - - debugfs_create_file(name, mode, sdev->debugfs_root, dfse, fops); - /* add to dfsentry list */ - list_add(&dfse->list, &sdev->dfsentry_list); - - return 0; -} -#endif - - static ssize_t sof_dfsentry_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { @@ -439,17 +223,6 @@ int snd_sof_dbg_init(struct snd_sof_dev *sdev) return err; } -#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) - err = snd_sof_debugfs_probe_item(sdev, "probe_points", - 0644, &probe_points_fops); - if (err < 0) - return err; - err = snd_sof_debugfs_probe_item(sdev, "probe_points_remove", - 0200, &probe_points_remove_fops); - if (err < 0) - return err; -#endif - return 0; } EXPORT_SYMBOL_GPL(snd_sof_dbg_init); diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 1acec1176986..35965e2e72de 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -557,20 +557,5 @@ struct snd_soc_dai_driver skl_dai[] = { .channels_max = 16, }, }, -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_PROBES) -{ - .name = "Probe Extraction CPU DAI", - .compress_new = snd_soc_new_compress, - .cops = &sof_probe_compr_ops, - .capture = { - .stream_name = "Probe Extraction", - .channels_min = 1, - .channels_max = 8, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, - }, -}, -#endif #endif }; diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 1bc4dabdd394..f0ac57e8b243 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -352,13 +352,7 @@ /* Number of DAIs */ #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) - -#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_PROBES) -#define SOF_SKL_NUM_DAIS 16 -#else #define SOF_SKL_NUM_DAIS 15 -#endif - #else #define SOF_SKL_NUM_DAIS 8 #endif diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index cbac6f17c52f..609583f79aa8 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -16,9 +16,6 @@ #include "sof-priv.h" #include "sof-audio.h" #include "ops.h" -#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) -#include "compress.h" -#endif /* Create DMA buffer page table for DSP */ static int create_page_table(struct snd_soc_component *component, @@ -801,14 +798,6 @@ void snd_sof_new_platform_drv(struct snd_sof_dev *sdev) pd->hw_free = sof_pcm_hw_free; pd->trigger = sof_pcm_trigger; pd->pointer = sof_pcm_pointer; - -#if IS_ENABLED(CONFIG_SND_SOC_SOF_COMPRESS) - pd->compress_ops = &sof_compressed_ops; -#endif -#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) - /* override cops when probe support is enabled */ - pd->compress_ops = &sof_probe_compressed_ops; -#endif pd->pcm_construct = sof_pcm_new; pd->ignore_machine = drv_name; pd->be_hw_params_fixup = sof_pcm_dai_link_fixup; diff --git a/sound/soc/sof/probe.c b/sound/soc/sof/probe.c index 14509f4d3f86..a926619b484a 100644 --- a/sound/soc/sof/probe.c +++ b/sound/soc/sof/probe.c @@ -8,12 +8,15 @@ // Author: Cezary Rojewski // -#include "sof-priv.h" +#include +#include #include "probe.h" +#include "sof-client.h" + /** - * sof_ipc_probe_init - initialize data probing - * @sdev: SOF sound device + * sof_probe_init - initialize data probing + * @cdev: SOF client device * @stream_tag: Extractor stream tag * @buffer_size: DMA buffer size to set for extractor * @@ -25,8 +28,8 @@ * Probing is initialized only once and each INIT request must be * matched by DEINIT call. */ -int sof_ipc_probe_init(struct snd_sof_dev *sdev, - u32 stream_tag, size_t buffer_size) +int sof_probe_init(struct sof_client_dev *cdev, u32 stream_tag, + size_t buffer_size) { struct sof_ipc_probe_dma_add_params *msg; struct sof_ipc_reply reply; @@ -42,22 +45,22 @@ int sof_ipc_probe_init(struct snd_sof_dev *sdev, msg->dma[0].stream_tag = stream_tag; msg->dma[0].dma_buffer_size = buffer_size; - ret = sof_ipc_tx_message(sdev->ipc, msg->hdr.cmd, msg, msg->hdr.size, - &reply, sizeof(reply)); + ret = sof_client_ipc_tx_message(cdev, msg->hdr.cmd, msg, msg->hdr.size, + &reply, sizeof(reply)); kfree(msg); return ret; } -EXPORT_SYMBOL(sof_ipc_probe_init); +EXPORT_SYMBOL(sof_probe_init); /** - * sof_ipc_probe_deinit - cleanup after data probing - * @sdev: SOF sound device + * sof_probe_deinit - cleanup after data probing + * @cdev: SOF client device * * Host sends DEINIT request to free previously initialized probe * on DSP side once it is no longer needed. DEINIT only when there * are no probes connected and with all injectors detached. */ -int sof_ipc_probe_deinit(struct snd_sof_dev *sdev) +int sof_probe_deinit(struct sof_client_dev *cdev) { struct sof_ipc_cmd_hdr msg; struct sof_ipc_reply reply; @@ -65,13 +68,13 @@ int sof_ipc_probe_deinit(struct snd_sof_dev *sdev) msg.size = sizeof(msg); msg.cmd = SOF_IPC_GLB_PROBE | SOF_IPC_PROBE_DEINIT; - return sof_ipc_tx_message(sdev->ipc, msg.cmd, &msg, msg.size, - &reply, sizeof(reply)); + return sof_client_ipc_tx_message(cdev, msg.cmd, &msg, msg.size, + &reply, sizeof(reply)); } -EXPORT_SYMBOL(sof_ipc_probe_deinit); +EXPORT_SYMBOL(sof_probe_deinit); -static int sof_ipc_probe_info(struct snd_sof_dev *sdev, unsigned int cmd, - void **params, size_t *num_params) +static int sof_probe_info(struct sof_client_dev *cdev, unsigned int cmd, + void **params, size_t *num_params) { struct sof_ipc_probe_info_params msg = {{{0}}}; struct sof_ipc_probe_info_params *reply; @@ -87,8 +90,9 @@ static int sof_ipc_probe_info(struct snd_sof_dev *sdev, unsigned int cmd, msg.rhdr.hdr.size = sizeof(msg); msg.rhdr.hdr.cmd = SOF_IPC_GLB_PROBE | cmd; - ret = sof_ipc_tx_message(sdev->ipc, msg.rhdr.hdr.cmd, &msg, - msg.rhdr.hdr.size, reply, SOF_IPC_MSG_MAX_SIZE); + ret = sof_client_ipc_tx_message(cdev, msg.rhdr.hdr.cmd, &msg, + msg.rhdr.hdr.size, reply, + SOF_IPC_MSG_MAX_SIZE); if (ret < 0 || reply->rhdr.error < 0) goto exit; @@ -113,8 +117,8 @@ static int sof_ipc_probe_info(struct snd_sof_dev *sdev, unsigned int cmd, } /** - * sof_ipc_probe_dma_info - retrieve list of active injection dmas - * @sdev: SOF sound device + * sof_probe_dma_info - retrieve list of active injection dmas + * @cdev: SOF client device * @dma: Returned list of active dmas * @num_dma: Returned count of active dmas * @@ -127,17 +131,17 @@ static int sof_ipc_probe_info(struct snd_sof_dev *sdev, unsigned int cmd, * which is not the case for injection where multiple streams * could be engaged. */ -int sof_ipc_probe_dma_info(struct snd_sof_dev *sdev, - struct sof_probe_dma **dma, size_t *num_dma) +int sof_probe_dma_info(struct sof_client_dev *cdev, + struct sof_probe_dma **dma, size_t *num_dma) { - return sof_ipc_probe_info(sdev, SOF_IPC_PROBE_DMA_INFO, - (void **)dma, num_dma); + return sof_probe_info(cdev, SOF_IPC_PROBE_DMA_INFO, + (void **)dma, num_dma); } -EXPORT_SYMBOL(sof_ipc_probe_dma_info); +EXPORT_SYMBOL(sof_probe_dma_info); /** - * sof_ipc_probe_dma_add - attach to specified dmas - * @sdev: SOF sound device + * sof_probe_dma_add - attach to specified dmas + * @cdev: SOF client device * @dma: List of streams (dmas) to attach to * @num_dma: Number of elements in @dma * @@ -146,8 +150,8 @@ EXPORT_SYMBOL(sof_ipc_probe_dma_info); * for specifying streams which will be later used to transfer data * to connected probe points. */ -int sof_ipc_probe_dma_add(struct snd_sof_dev *sdev, - struct sof_probe_dma *dma, size_t num_dma) +int sof_probe_dma_add(struct sof_client_dev *cdev, + struct sof_probe_dma *dma, size_t num_dma) { struct sof_ipc_probe_dma_add_params *msg; struct sof_ipc_reply reply; @@ -162,16 +166,16 @@ int sof_ipc_probe_dma_add(struct snd_sof_dev *sdev, msg->hdr.cmd = SOF_IPC_GLB_PROBE | SOF_IPC_PROBE_DMA_ADD; memcpy(&msg->dma[0], dma, size - sizeof(*msg)); - ret = sof_ipc_tx_message(sdev->ipc, msg->hdr.cmd, msg, msg->hdr.size, - &reply, sizeof(reply)); + ret = sof_client_ipc_tx_message(cdev, msg->hdr.cmd, msg, msg->hdr.size, + &reply, sizeof(reply)); kfree(msg); return ret; } -EXPORT_SYMBOL(sof_ipc_probe_dma_add); +EXPORT_SYMBOL(sof_probe_dma_add); /** - * sof_ipc_probe_dma_remove - detach from specified dmas - * @sdev: SOF sound device + * sof_probe_dma_remove - detach from specified dmas + * @cdev: SOF client device * @stream_tag: List of stream tags to detach from * @num_stream_tag: Number of elements in @stream_tag * @@ -180,8 +184,8 @@ EXPORT_SYMBOL(sof_ipc_probe_dma_add); * match equivalent DMA_ADD. Detach only when all probes tied to * given stream have been disconnected. */ -int sof_ipc_probe_dma_remove(struct snd_sof_dev *sdev, - unsigned int *stream_tag, size_t num_stream_tag) +int sof_probe_dma_remove(struct sof_client_dev *cdev, + unsigned int *stream_tag, size_t num_stream_tag) { struct sof_ipc_probe_dma_remove_params *msg; struct sof_ipc_reply reply; @@ -196,16 +200,16 @@ int sof_ipc_probe_dma_remove(struct snd_sof_dev *sdev, msg->hdr.cmd = SOF_IPC_GLB_PROBE | SOF_IPC_PROBE_DMA_REMOVE; memcpy(&msg->stream_tag[0], stream_tag, size - sizeof(*msg)); - ret = sof_ipc_tx_message(sdev->ipc, msg->hdr.cmd, msg, msg->hdr.size, - &reply, sizeof(reply)); + ret = sof_client_ipc_tx_message(cdev, msg->hdr.cmd, msg, msg->hdr.size, + &reply, sizeof(reply)); kfree(msg); return ret; } -EXPORT_SYMBOL(sof_ipc_probe_dma_remove); +EXPORT_SYMBOL(sof_probe_dma_remove); /** - * sof_ipc_probe_points_info - retrieve list of active probe points - * @sdev: SOF sound device + * sof_probe_points_info - retrieve list of active probe points + * @cdev: SOF client device * @desc: Returned list of active probes * @num_desc: Returned count of active probes * @@ -213,17 +217,18 @@ EXPORT_SYMBOL(sof_ipc_probe_dma_remove); * points, valid for disconnection when given probe is no longer * required. */ -int sof_ipc_probe_points_info(struct snd_sof_dev *sdev, - struct sof_probe_point_desc **desc, size_t *num_desc) +int sof_probe_points_info(struct sof_client_dev *cdev, + struct sof_probe_point_desc **desc, + size_t *num_desc) { - return sof_ipc_probe_info(sdev, SOF_IPC_PROBE_POINT_INFO, + return sof_probe_info(cdev, SOF_IPC_PROBE_POINT_INFO, (void **)desc, num_desc); } -EXPORT_SYMBOL(sof_ipc_probe_points_info); +EXPORT_SYMBOL(sof_probe_points_info); /** - * sof_ipc_probe_points_add - connect specified probes - * @sdev: SOF sound device + * sof_probe_points_add - connect specified probes + * @cdev: SOF client device * @desc: List of probe points to connect * @num_desc: Number of elements in @desc * @@ -234,8 +239,9 @@ EXPORT_SYMBOL(sof_ipc_probe_points_info); * Each probe point should be removed using PROBE_POINT_REMOVE * request when no longer needed. */ -int sof_ipc_probe_points_add(struct snd_sof_dev *sdev, - struct sof_probe_point_desc *desc, size_t num_desc) +int sof_probe_points_add(struct sof_client_dev *cdev, + struct sof_probe_point_desc *desc, + size_t num_desc) { struct sof_ipc_probe_point_add_params *msg; struct sof_ipc_reply reply; @@ -250,24 +256,24 @@ int sof_ipc_probe_points_add(struct snd_sof_dev *sdev, msg->hdr.cmd = SOF_IPC_GLB_PROBE | SOF_IPC_PROBE_POINT_ADD; memcpy(&msg->desc[0], desc, size - sizeof(*msg)); - ret = sof_ipc_tx_message(sdev->ipc, msg->hdr.cmd, msg, msg->hdr.size, - &reply, sizeof(reply)); + ret = sof_client_ipc_tx_message(cdev, msg->hdr.cmd, msg, msg->hdr.size, + &reply, sizeof(reply)); kfree(msg); return ret; } -EXPORT_SYMBOL(sof_ipc_probe_points_add); +EXPORT_SYMBOL(sof_probe_points_add); /** - * sof_ipc_probe_points_remove - disconnect specified probes - * @sdev: SOF sound device + * sof_probe_points_remove - disconnect specified probes + * @cdev: SOF client device * @buffer_id: List of probe points to disconnect * @num_buffer_id: Number of elements in @desc * * Removes previously connected probes from list of active probe * points and frees all resources on DSP side. */ -int sof_ipc_probe_points_remove(struct snd_sof_dev *sdev, - unsigned int *buffer_id, size_t num_buffer_id) +int sof_probe_points_remove(struct sof_client_dev *cdev, + unsigned int *buffer_id, size_t num_buffer_id) { struct sof_ipc_probe_point_remove_params *msg; struct sof_ipc_reply reply; @@ -282,9 +288,9 @@ int sof_ipc_probe_points_remove(struct snd_sof_dev *sdev, msg->hdr.cmd = SOF_IPC_GLB_PROBE | SOF_IPC_PROBE_POINT_REMOVE; memcpy(&msg->buffer_id[0], buffer_id, size - sizeof(*msg)); - ret = sof_ipc_tx_message(sdev->ipc, msg->hdr.cmd, msg, msg->hdr.size, - &reply, sizeof(reply)); + ret = sof_client_ipc_tx_message(cdev, msg->hdr.cmd, msg, msg->hdr.size, + &reply, sizeof(reply)); kfree(msg); return ret; } -EXPORT_SYMBOL(sof_ipc_probe_points_remove); +EXPORT_SYMBOL(sof_probe_points_remove); diff --git a/sound/soc/sof/probe.h b/sound/soc/sof/probe.h index 5e159ab239fa..42e802b7e7fc 100644 --- a/sound/soc/sof/probe.h +++ b/sound/soc/sof/probe.h @@ -12,8 +12,8 @@ #define __SOF_PROBE_H #include - -struct snd_sof_dev; +#include +#include "sof-client.h" #define SOF_PROBE_INVALID_NODE_ID UINT_MAX @@ -66,20 +66,27 @@ struct sof_ipc_probe_point_remove_params { unsigned int buffer_id[]; } __packed; -int sof_ipc_probe_init(struct snd_sof_dev *sdev, - u32 stream_tag, size_t buffer_size); -int sof_ipc_probe_deinit(struct snd_sof_dev *sdev); -int sof_ipc_probe_dma_info(struct snd_sof_dev *sdev, - struct sof_probe_dma **dma, size_t *num_dma); -int sof_ipc_probe_dma_add(struct snd_sof_dev *sdev, - struct sof_probe_dma *dma, size_t num_dma); -int sof_ipc_probe_dma_remove(struct snd_sof_dev *sdev, - unsigned int *stream_tag, size_t num_stream_tag); -int sof_ipc_probe_points_info(struct snd_sof_dev *sdev, - struct sof_probe_point_desc **desc, size_t *num_desc); -int sof_ipc_probe_points_add(struct snd_sof_dev *sdev, - struct sof_probe_point_desc *desc, size_t num_desc); -int sof_ipc_probe_points_remove(struct snd_sof_dev *sdev, - unsigned int *buffer_id, size_t num_buffer_id); +int sof_probe_init(struct sof_client_dev *cdev, u32 stream_tag, + size_t buffer_size); +int sof_probe_deinit(struct sof_client_dev *cdev); +int sof_probe_dma_info(struct sof_client_dev *cdev, + struct sof_probe_dma **dma, size_t *num_dma); +int sof_probe_dma_add(struct sof_client_dev *cdev, + struct sof_probe_dma *dma, size_t num_dma); +int sof_probe_dma_remove(struct sof_client_dev *cdev, + unsigned int *stream_tag, size_t num_stream_tag); +int sof_probe_points_info(struct sof_client_dev *cdev, + struct sof_probe_point_desc **desc, + size_t *num_desc); +int sof_probe_points_add(struct sof_client_dev *cdev, + struct sof_probe_point_desc *desc, + size_t num_desc); +int sof_probe_points_remove(struct sof_client_dev *cdev, + unsigned int *buffer_id, size_t num_buffer_id); + +struct sof_probes_data { + struct dentry *dfs_root; + unsigned int extractor_stream_tag; +}; #endif diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index e44158410b24..121c374297fc 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -425,10 +425,6 @@ struct snd_sof_dev { int ipc_timeout; int boot_timeout; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) - unsigned int extractor_stream_tag; -#endif - /* DMA for Trace */ struct snd_dma_buffer dmatb; struct snd_dma_buffer dmatp; diff --git a/sound/soc/sof/sof-probes-client.c b/sound/soc/sof/sof-probes-client.c new file mode 100644 index 000000000000..73227af3d339 --- /dev/null +++ b/sound/soc/sof/sof-probes-client.c @@ -0,0 +1,414 @@ +// SPDX-License-Identifier: (GPL-2.0-only) +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Ranjani Sridharan +// + +#include +#include +#include +#include +#include +#include +#include +#include "compress.h" +#include "probe.h" +#include "sof-client.h" + +#define SOF_PROBES_SUSPEND_DELAY_MS 3000 +/* only extraction supported for now */ +#define SOF_PROBES_NUM_DAI_LINKS 1 + +/** + * strsplit_u32 - Split string into sequence of u32 tokens + * @buf: String to split into tokens. + * @delim: String containing delimiter characters. + * @tkns: Returned u32 sequence pointer. + * @num_tkns: Returned number of tokens obtained. + */ +static int +strsplit_u32(char *buf, const char *delim, u32 **tkns, size_t *num_tkns) +{ + char *s; + u32 *data, *tmp; + size_t count = 0; + size_t cap = 32; + int ret = 0; + + *tkns = NULL; + *num_tkns = 0; + data = kcalloc(cap, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + while ((s = strsep(&buf, delim)) != NULL) { + ret = kstrtouint(s, 0, data + count); + if (ret) + goto exit; + if (++count >= cap) { + cap *= 2; + tmp = krealloc(data, cap * sizeof(*data), GFP_KERNEL); + if (!tmp) { + ret = -ENOMEM; + goto exit; + } + data = tmp; + } + } + + if (!count) + goto exit; + *tkns = kmemdup(data, count * sizeof(*data), GFP_KERNEL); + if (!(*tkns)) { + ret = -ENOMEM; + goto exit; + } + *num_tkns = count; + +exit: + kfree(data); + return ret; +} + +static int tokenize_input(const char __user *from, size_t count, + loff_t *ppos, u32 **tkns, size_t *num_tkns) +{ + char *buf; + int ret; + + buf = kmalloc(count + 1, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = simple_write_to_buffer(buf, count, ppos, from, count); + if (ret != count) { + ret = ret >= 0 ? -EIO : ret; + goto exit; + } + + buf[count] = '\0'; + ret = strsplit_u32(buf, ",", tkns, num_tkns); +exit: + kfree(buf); + return ret; +} + +static ssize_t probe_points_read(struct file *file, char __user *to, + size_t count, loff_t *ppos) +{ + struct sof_client_dev *cdev = file->private_data; + struct sof_probes_data *probes_data = cdev->data; + struct device *dev = &cdev->auxdev.dev; + struct sof_probe_point_desc *desc; + size_t num_desc; + int remaining; + char *buf; + int i, ret, err; + + if (probes_data->extractor_stream_tag == SOF_PROBE_INVALID_NODE_ID) { + dev_warn(dev, "no extractor stream running\n"); + return -ENOENT; + } + + buf = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = pm_runtime_get_sync(dev); + if (ret < 0 && ret != -EACCES) { + dev_err_ratelimited(dev, "error: debugfs read failed to resume %d\n", ret); + pm_runtime_put_noidle(dev); + goto exit; + } + + ret = sof_probe_points_info(cdev, &desc, &num_desc); + if (ret < 0) + goto exit; + + pm_runtime_mark_last_busy(dev); + err = pm_runtime_put_autosuspend(dev); + if (err < 0) + dev_err_ratelimited(dev, "error: debugfs read failed to idle %d\n", err); + + for (i = 0; i < num_desc; i++) { + remaining = PAGE_SIZE - strlen(buf); + if (remaining > 0) { + ret = snprintf(buf + strlen(buf), remaining, + "Id: %#010x Purpose: %u Node id: %#x\n", + desc[i].buffer_id, desc[i].purpose, desc[i].stream_tag); + if (ret < 0) + goto free_desc; + } else { + break; + } + } + + ret = simple_read_from_buffer(to, count, ppos, buf, strlen(buf)); +free_desc: + kfree(desc); +exit: + kfree(buf); + return ret; +} + +static ssize_t probe_points_write(struct file *file, const char __user *from, + size_t count, loff_t *ppos) +{ + struct sof_client_dev *cdev = file->private_data; + struct sof_probes_data *probes_data = cdev->data; + struct device *dev = &cdev->auxdev.dev; + struct sof_probe_point_desc *desc; + size_t num_tkns, bytes; + u32 *tkns; + int ret, err; + + if (probes_data->extractor_stream_tag == SOF_PROBE_INVALID_NODE_ID) { + dev_warn(dev, "no extractor stream running\n"); + return -ENOENT; + } + + ret = tokenize_input(from, count, ppos, &tkns, &num_tkns); + if (ret < 0) + return ret; + bytes = sizeof(*tkns) * num_tkns; + if (!num_tkns || (bytes % sizeof(*desc))) { + ret = -EINVAL; + goto exit; + } + + desc = (struct sof_probe_point_desc *)tkns; + + ret = pm_runtime_get_sync(dev); + if (ret < 0 && ret != -EACCES) { + dev_err_ratelimited(dev, "error: debugfs write failed to resume %d\n", ret); + pm_runtime_put_noidle(dev); + goto exit; + } + + ret = sof_probe_points_add(cdev, desc, bytes / sizeof(*desc)); + if (!ret) + ret = count; + + pm_runtime_mark_last_busy(dev); + err = pm_runtime_put_autosuspend(dev); + if (err < 0) + dev_err_ratelimited(dev, "error: debugfs write failed to idle %d\n", err); +exit: + kfree(tkns); + return ret; +} + +static const struct file_operations probe_points_fops = { + .open = simple_open, + .read = probe_points_read, + .write = probe_points_write, + .llseek = default_llseek, +}; + +static ssize_t +probe_points_remove_write(struct file *file, const char __user *from, + size_t count, loff_t *ppos) +{ + struct sof_client_dev *cdev = file->private_data; + struct sof_probes_data *probes_data = cdev->data; + struct device *dev = &cdev->auxdev.dev; + size_t num_tkns; + u32 *tkns; + int ret, err; + + if (probes_data->extractor_stream_tag == SOF_PROBE_INVALID_NODE_ID) { + dev_warn(dev, "no extractor stream running\n"); + return -ENOENT; + } + + ret = tokenize_input(from, count, ppos, &tkns, &num_tkns); + if (ret < 0) + return ret; + if (!num_tkns) { + ret = -EINVAL; + goto exit; + } + + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + dev_err_ratelimited(dev, "error: debugfs write failed to resume %d\n", ret); + pm_runtime_put_noidle(dev); + goto exit; + } + + ret = sof_probe_points_remove(cdev, tkns, num_tkns); + if (!ret) + ret = count; + + pm_runtime_mark_last_busy(dev); + err = pm_runtime_put_autosuspend(dev); + if (err < 0) + dev_err_ratelimited(dev, "error: debugfs write failed to idle %d\n", err); +exit: + kfree(tkns); + return ret; +} + +static const struct file_operations probe_points_remove_fops = { + .open = simple_open, + .write = probe_points_remove_write, + .llseek = default_llseek, +}; + +struct snd_soc_dai_driver sof_probes_dai_drv[] = { +{ + .name = "Probe Extraction CPU DAI", + .compress_new = snd_soc_new_compress, + .cops = &sof_probe_compr_ops, + .capture = { + .stream_name = "Probe Extraction", + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + }, +}, +}; + +static const struct snd_soc_component_driver sof_probes_component = { + .name = "sof-probes-component", + .compress_ops = &sof_probe_compressed_ops, + .module_get_upon_open = 1, +}; + +SND_SOC_DAILINK_DEF(dummy, DAILINK_COMP_ARRAY(COMP_DUMMY())); + +static struct snd_soc_card sof_probes_card = { + .name = "sof-probes", + .owner = THIS_MODULE +}; + +static int sof_probes_client_probe(struct auxiliary_device *auxdev, + const struct auxiliary_device_id *id) +{ + struct sof_client_dev *cdev = auxiliary_dev_to_sof_client_dev(auxdev); + struct snd_soc_dai_link_component platform_component[] = { + { + .name = dev_name(&auxdev->dev), + } + }; + struct snd_soc_card *card = &sof_probes_card; + struct sof_probes_data *probes_client_data; + struct snd_soc_dai_link_component *cpus; + struct snd_soc_dai_link *links; + int ret; + + /* register probes component driver and dai */ + ret = devm_snd_soc_register_component(&auxdev->dev, &sof_probes_component, + sof_probes_dai_drv, ARRAY_SIZE(sof_probes_dai_drv)); + if (ret < 0) { + dev_err(&auxdev->dev, "error: failed to register SOF probes DAI driver %d\n", ret); + return ret; + } + + /* set client data */ + probes_client_data = devm_kzalloc(&auxdev->dev, sizeof(*probes_client_data), GFP_KERNEL); + if (!probes_client_data) + return -ENOMEM; + + probes_client_data->extractor_stream_tag = SOF_PROBE_INVALID_NODE_ID; + cdev->data = probes_client_data; + + /* create probes debugfs dir under SOF debugfs root dir */ + probes_client_data->dfs_root = debugfs_create_dir("probes", + sof_client_get_debugfs_root(cdev)); + + /* create read-write probes_points debugfs entry */ + debugfs_create_file("probe_points", 0644, probes_client_data->dfs_root, + cdev, &probe_points_fops); + + /* create read-write probe_points_remove debugfs entry */ + debugfs_create_file("probe_points_remove", 0644, probes_client_data->dfs_root, + cdev, &probe_points_remove_fops); + + links = devm_kzalloc(&auxdev->dev, sizeof(*links) * SOF_PROBES_NUM_DAI_LINKS, GFP_KERNEL); + cpus = devm_kzalloc(&auxdev->dev, sizeof(*cpus) * SOF_PROBES_NUM_DAI_LINKS, GFP_KERNEL); + if (!links || !cpus) + return -ENOMEM; + + /* extraction DAI link */ + links[0].name = "Compress Probe Capture"; + links[0].id = 0; + links[0].cpus = &cpus[0]; + links[0].num_cpus = 1; + links[0].cpus->dai_name = "Probe Extraction CPU DAI"; + links[0].codecs = dummy; + links[0].num_codecs = 1; + links[0].platforms = platform_component; + links[0].num_platforms = ARRAY_SIZE(platform_component); + links[0].nonatomic = 1; + + card->num_links = SOF_PROBES_NUM_DAI_LINKS; + card->dai_link = links; + card->dev = &auxdev->dev; + + /* set idle_bias_off to prevent the core from resuming the card->dev */ + card->dapm.idle_bias_off = true; + + snd_soc_card_set_drvdata(&sof_probes_card, cdev); + + ret = devm_snd_soc_register_card(&auxdev->dev, card); + if (ret < 0) { + dev_err(&auxdev->dev, "error: Probes card register failed %d\n", ret); + return ret; + } + + /* enable runtime PM */ + pm_runtime_set_autosuspend_delay(&auxdev->dev, SOF_PROBES_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(&auxdev->dev); + pm_runtime_enable(&auxdev->dev); + pm_runtime_mark_last_busy(&auxdev->dev); + pm_runtime_idle(&auxdev->dev); + + return 0; +} + +static int sof_probes_client_cleanup(struct auxiliary_device *auxdev) +{ + struct sof_client_dev *cdev = auxiliary_dev_to_sof_client_dev(auxdev); + struct sof_probes_data *probes_client_data = cdev->data; + + pm_runtime_disable(&auxdev->dev); + debugfs_remove_recursive(probes_client_data->dfs_root); + + return 0; +} + +static int sof_probes_client_remove(struct auxiliary_device *auxdev) +{ + return sof_probes_client_cleanup(auxdev); +} + +static void sof_probes_client_shutdown(struct auxiliary_device *auxdev) +{ + sof_probes_client_cleanup(auxdev); +} + +static const struct auxiliary_device_id sof_probes_auxbus_id_table[] = { + { .name = "snd_sof_client.probes" }, + {}, +}; +MODULE_DEVICE_TABLE(auxiliary, sof_probes_auxbus_id_table); + +/* driver name will be set based on KBUILD_MODNAME */ +static struct sof_client_drv sof_probes_test_client_drv = { + .auxiliary_drv = { + .id_table = sof_probes_auxbus_id_table, + .probe = sof_probes_client_probe, + .remove = sof_probes_client_remove, + .shutdown = sof_probes_client_shutdown, + }, +}; + +module_sof_client_driver(sof_probes_test_client_drv); + +MODULE_DESCRIPTION("SOF Probes Client Driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT); From patchwork Fri Oct 23 00:33:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Ertman X-Patchwork-Id: 11852125 X-Patchwork-Delegate: kuba@kernel.org 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=-12.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, 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 EE37AC388F7 for ; Fri, 23 Oct 2020 00:35:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BF28024650 for ; Fri, 23 Oct 2020 00:35:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S373920AbgJWAfg (ORCPT ); Thu, 22 Oct 2020 20:35:36 -0400 Received: from mga11.intel.com ([192.55.52.93]:43009 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S373864AbgJWAfa (ORCPT ); Thu, 22 Oct 2020 20:35:30 -0400 IronPort-SDR: igoJ/56H5YAygkgJOWJaBHtXaEFukSA2G3jDMGvLkkfa9qeypL8ICdKMxmc8HO6U/QFQYF8Exb 0g0PXeSsa/Zg== X-IronPort-AV: E=McAfee;i="6000,8403,9782"; a="164118655" X-IronPort-AV: E=Sophos;i="5.77,404,1596524400"; d="scan'208";a="164118655" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Oct 2020 17:35:29 -0700 IronPort-SDR: AmNrptTHi/qxndARhN2/6LgX9EtDqEMC7c+p3z+rBNqomsEsGFcmp6cWKzFipvTpj3fv7+DjD3 tghWbrJuAywg== X-IronPort-AV: E=Sophos;i="5.77,404,1596524400"; d="scan'208";a="302505834" Received: from dmert-dev.jf.intel.com ([10.166.241.5]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Oct 2020 17:35:28 -0700 From: Dave Ertman To: alsa-devel@alsa-project.org Cc: tiwai@suse.de, broonie@kernel.org, linux-rdma@vger.kernel.org, jgg@nvidia.com, dledford@redhat.com, netdev@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, gregkh@linuxfoundation.org, ranjani.sridharan@linux.intel.com, pierre-louis.bossart@linux.intel.com, fred.oh@linux.intel.com, parav@mellanox.com, shiraz.saleem@intel.com, dan.j.williams@intel.com, kiran.patil@intel.com, linux-kernel@vger.kernel.org, leonro@nvidia.com Subject: [PATCH v3 10/10] ASoC: SOF: Intel: CNL: register probes client Date: Thu, 22 Oct 2020 17:33:38 -0700 Message-Id: <20201023003338.1285642-11-david.m.ertman@intel.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201023003338.1285642-1-david.m.ertman@intel.com> References: <20201023003338.1285642-1-david.m.ertman@intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Ranjani Sridharan Register the client device for probes support on the CNL platform. Creating this client device alleviates the need for modifying the sound card definitions in the existing machine drivers to add support for the new probes feature in the FW. This will result in the creation of a separate sound card that can be used for audio data extraction from user specified points in the audio pipeline. Reviewed-by: Pierre-Louis Bossart Tested-by: Fred Oh Signed-off-by: Ranjani Sridharan Signed-off-by: Dave Ertman --- sound/soc/sof/intel/cnl.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 20afb622c315..6d15b871dc17 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -19,6 +19,7 @@ #include "hda.h" #include "hda-ipc.h" #include "../sof-audio.h" +#include "../sof-client.h" #include "intel-client.h" static const struct snd_sof_debugfs_map cnl_dsp_debugfs[] = { @@ -233,12 +234,26 @@ void cnl_ipc_dump(struct snd_sof_dev *sdev) static int cnl_register_clients(struct snd_sof_dev *sdev) { - return intel_register_ipc_test_clients(sdev); + int ret; + + ret = intel_register_ipc_test_clients(sdev); + if (ret < 0) + return ret; + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_PROBES) + return sof_client_dev_register(sdev, "probes", 0); +#endif + + return 0; } static void cnl_unregister_clients(struct snd_sof_dev *sdev) { intel_unregister_ipc_test_clients(sdev); + +#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_PROBES) + sof_client_dev_unregister(sdev, "probes", 0); +#endif } /* cannonlake ops */ @@ -409,3 +424,4 @@ const struct sof_intel_dsp_desc jsl_chip_info = { }; EXPORT_SYMBOL_NS(jsl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_CLIENT); +MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT);