Commit 7bbdda80 authored by Peter Ujfalusi's avatar Peter Ujfalusi Committed by Mark Brown

ASoC: SOF: probe: Merge and clean up the probe and compress files

The probe debug functionality is implemented via compress support and it
was spread across two set of files:
probe.c/h
compress.c/h

Merge the two files into sof-probes.s/h and clean them up by removing
unused struct definitions, functions. We can also move most of the
functions static as they are only used internally.
Signed-off-by: default avatarPeter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: default avatarKai Vehmanen <kai.vehmanen@linux.intel.com>
Reviewed-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Link: https://lore.kernel.org/r/20210916103211.1573-5-peter.ujfalusi@linux.intel.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 2dc51106
......@@ -2,7 +2,8 @@
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-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES) += probe.o compress.o
snd-sof-$(CONFIG_SND_SOC_SOF_DEBUG_PROBES) += sof-probes.o
snd-sof-pci-objs := sof-pci-dev.o
snd-sof-acpi-objs := sof-acpi-dev.o
......
// 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) 2019-2020 Intel Corporation. All rights reserved.
//
// Author: Cezary Rojewski <cezary.rojewski@intel.com>
//
#include <sound/soc.h>
#include "compress.h"
#include "ops.h"
#include "probe.h"
static 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);
int ret;
ret = snd_sof_probe_compr_assign(sdev, cstream, dai);
if (ret < 0) {
dev_err(dai->dev, "Failed to assign probe stream: %d\n", ret);
return ret;
}
sdev->extractor_stream_tag = ret;
return 0;
}
static 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 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);
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);
kfree(desc);
exit:
ret = sof_ipc_probe_deinit(sdev);
if (ret < 0)
dev_err(dai->dev, "Failed to deinit probe: %d\n", ret);
sdev->extractor_stream_tag = SOF_PROBE_INVALID_NODE_ID;
snd_compr_free_pages(cstream);
return snd_sof_probe_compr_free(sdev, cstream, dai);
}
static int sof_probe_compr_set_params(struct snd_compr_stream *cstream,
struct snd_compr_params *params,
struct snd_soc_dai *dai)
{
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;
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);
if (ret < 0)
return ret;
ret = sof_ipc_probe_init(sdev, sdev->extractor_stream_tag,
rtd->dma_bytes);
if (ret < 0) {
dev_err(dai->dev, "Failed to init probe: %d\n", ret);
return ret;
}
return 0;
}
static 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);
return snd_sof_probe_compr_trigger(sdev, cstream, cmd, dai);
}
static 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);
return snd_sof_probe_compr_pointer(sdev, cstream, tstamp, dai);
}
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);
static int sof_probe_compr_copy(struct snd_soc_component *component,
struct snd_compr_stream *cstream,
char __user *buf, size_t count)
{
struct snd_compr_runtime *rtd = cstream->runtime;
unsigned int offset, n;
void *ptr;
int ret;
if (count > rtd->buffer_size)
count = rtd->buffer_size;
div_u64_rem(rtd->total_bytes_transferred, rtd->buffer_size, &offset);
ptr = rtd->dma_area + offset;
n = rtd->buffer_size - offset;
if (count < n) {
ret = copy_to_user(buf, ptr, count);
} else {
ret = copy_to_user(buf, ptr, n);
ret += copy_to_user(buf + n, rtd->dma_area, count - n);
}
if (ret)
return count - ret;
return count;
}
const struct snd_compress_ops sof_probe_compressed_ops = {
.copy = sof_probe_compr_copy,
};
EXPORT_SYMBOL(sof_probe_compressed_ops);
......@@ -15,7 +15,7 @@
#include "sof-priv.h"
#include "ops.h"
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
#include "probe.h"
#include "sof-probes.h"
#endif
/* see SOF_DBG_ flags */
......
......@@ -20,7 +20,7 @@
#include "ops.h"
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
#include "probe.h"
#include "sof-probes.h"
/**
* strsplit_u32 - Split string into sequence of u32 tokens
......
......@@ -17,7 +17,7 @@
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
#include "../compress.h"
#include "../sof-probes.h"
#endif
struct hda_pipe_params {
......
......@@ -17,7 +17,7 @@
#include "sof-audio.h"
#include "ops.h"
#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
#include "compress.h"
#include "sof-probes.h"
#endif
/* Create DMA buffer page table for DSP */
......
/* 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) 2019-2020 Intel Corporation. All rights reserved.
*
* Author: Cezary Rojewski <cezary.rojewski@intel.com>
*/
#ifndef __SOF_PROBE_H
#define __SOF_PROBE_H
#include <sound/sof/header.h>
struct snd_sof_dev;
#define SOF_PROBE_INVALID_NODE_ID UINT_MAX
struct sof_probe_dma {
unsigned int stream_tag;
unsigned int dma_buffer_size;
} __packed;
enum sof_connection_purpose {
SOF_CONNECTION_PURPOSE_EXTRACT = 1,
SOF_CONNECTION_PURPOSE_INJECT,
};
struct sof_probe_point_desc {
unsigned int buffer_id;
unsigned int purpose;
unsigned int stream_tag;
} __packed;
struct sof_ipc_probe_dma_add_params {
struct sof_ipc_cmd_hdr hdr;
unsigned int num_elems;
struct sof_probe_dma dma[];
} __packed;
struct sof_ipc_probe_info_params {
struct sof_ipc_reply rhdr;
unsigned int num_elems;
union {
struct sof_probe_dma dma[0];
struct sof_probe_point_desc desc[0];
};
} __packed;
struct sof_ipc_probe_dma_remove_params {
struct sof_ipc_cmd_hdr hdr;
unsigned int num_elems;
unsigned int stream_tag[];
} __packed;
struct sof_ipc_probe_point_add_params {
struct sof_ipc_cmd_hdr hdr;
unsigned int num_elems;
struct sof_probe_point_desc desc[];
} __packed;
struct sof_ipc_probe_point_remove_params {
struct sof_ipc_cmd_hdr hdr;
unsigned int num_elems;
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);
#endif
......@@ -3,13 +3,46 @@
// 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) 2019-2020 Intel Corporation. All rights reserved.
//
// Copyright(c) 2019-2021 Intel Corporation. All rights reserved.
// Author: Cezary Rojewski <cezary.rojewski@intel.com>
//
#include <sound/soc.h>
#include "ops.h"
#include "sof-priv.h"
#include "probe.h"
#include "sof-probes.h"
struct sof_probe_dma {
unsigned int stream_tag;
unsigned int dma_buffer_size;
} __packed;
struct sof_ipc_probe_dma_add_params {
struct sof_ipc_cmd_hdr hdr;
unsigned int num_elems;
struct sof_probe_dma dma[];
} __packed;
struct sof_ipc_probe_info_params {
struct sof_ipc_reply rhdr;
unsigned int num_elems;
union {
struct sof_probe_dma dma[0];
struct sof_probe_point_desc desc[0];
};
} __packed;
struct sof_ipc_probe_point_add_params {
struct sof_ipc_cmd_hdr hdr;
unsigned int num_elems;
struct sof_probe_point_desc desc[];
} __packed;
struct sof_ipc_probe_point_remove_params {
struct sof_ipc_cmd_hdr hdr;
unsigned int num_elems;
unsigned int buffer_id[];
} __packed;
/**
* sof_ipc_probe_init - initialize data probing
......@@ -25,8 +58,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)
static int sof_ipc_probe_init(struct snd_sof_dev *sdev, u32 stream_tag,
size_t buffer_size)
{
struct sof_ipc_probe_dma_add_params *msg;
struct sof_ipc_reply reply;
......@@ -47,7 +80,6 @@ int sof_ipc_probe_init(struct snd_sof_dev *sdev,
kfree(msg);
return ret;
}
EXPORT_SYMBOL(sof_ipc_probe_init);
/**
* sof_ipc_probe_deinit - cleanup after data probing
......@@ -57,7 +89,7 @@ EXPORT_SYMBOL(sof_ipc_probe_init);
* 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)
static int sof_ipc_probe_deinit(struct snd_sof_dev *sdev)
{
struct sof_ipc_cmd_hdr msg;
struct sof_ipc_reply reply;
......@@ -68,7 +100,6 @@ int sof_ipc_probe_deinit(struct snd_sof_dev *sdev)
return sof_ipc_tx_message(sdev->ipc, msg.cmd, &msg, msg.size,
&reply, sizeof(reply));
}
EXPORT_SYMBOL(sof_ipc_probe_deinit);
static int sof_ipc_probe_info(struct snd_sof_dev *sdev, unsigned int cmd,
void **params, size_t *num_params)
......@@ -112,97 +143,6 @@ static int sof_ipc_probe_info(struct snd_sof_dev *sdev, unsigned int cmd,
return ret;
}
/**
* sof_ipc_probe_dma_info - retrieve list of active injection dmas
* @sdev: SOF sound device
* @dma: Returned list of active dmas
* @num_dma: Returned count of active dmas
*
* Host sends DMA_INFO request to obtain list of injection dmas it
* can use to transfer data over with.
*
* Note that list contains only injection dmas as there is only one
* extractor (dma) and it is always assigned on probing init.
* DSP knows exactly where data from extraction probes is going to,
* 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)
{
return sof_ipc_probe_info(sdev, SOF_IPC_PROBE_DMA_INFO,
(void **)dma, num_dma);
}
EXPORT_SYMBOL(sof_ipc_probe_dma_info);
/**
* sof_ipc_probe_dma_add - attach to specified dmas
* @sdev: SOF sound device
* @dma: List of streams (dmas) to attach to
* @num_dma: Number of elements in @dma
*
* Contrary to extraction, injection streams are never assigned
* on init. Before attempting any data injection, host is responsible
* 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)
{
struct sof_ipc_probe_dma_add_params *msg;
struct sof_ipc_reply reply;
size_t size = struct_size(msg, dma, num_dma);
int ret;
msg = kmalloc(size, GFP_KERNEL);
if (!msg)
return -ENOMEM;
msg->hdr.size = size;
msg->num_elems = num_dma;
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));
kfree(msg);
return ret;
}
EXPORT_SYMBOL(sof_ipc_probe_dma_add);
/**
* sof_ipc_probe_dma_remove - detach from specified dmas
* @sdev: SOF sound device
* @stream_tag: List of stream tags to detach from
* @num_stream_tag: Number of elements in @stream_tag
*
* Host sends DMA_REMOVE request to free previously attached stream
* from being occupied for injection. Each detach operation should
* 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)
{
struct sof_ipc_probe_dma_remove_params *msg;
struct sof_ipc_reply reply;
size_t size = struct_size(msg, stream_tag, num_stream_tag);
int ret;
msg = kmalloc(size, GFP_KERNEL);
if (!msg)
return -ENOMEM;
msg->hdr.size = size;
msg->num_elems = num_stream_tag;
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));
kfree(msg);
return ret;
}
EXPORT_SYMBOL(sof_ipc_probe_dma_remove);
/**
* sof_ipc_probe_points_info - retrieve list of active probe points
* @sdev: SOF sound device
......@@ -214,7 +154,8 @@ EXPORT_SYMBOL(sof_ipc_probe_dma_remove);
* required.
*/
int sof_ipc_probe_points_info(struct snd_sof_dev *sdev,
struct sof_probe_point_desc **desc, size_t *num_desc)
struct sof_probe_point_desc **desc,
size_t *num_desc)
{
return sof_ipc_probe_info(sdev, SOF_IPC_PROBE_POINT_INFO,
(void **)desc, num_desc);
......@@ -288,3 +229,136 @@ int sof_ipc_probe_points_remove(struct snd_sof_dev *sdev,
return ret;
}
EXPORT_SYMBOL(sof_ipc_probe_points_remove);
static 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);
int ret;
ret = snd_sof_probe_compr_assign(sdev, cstream, dai);
if (ret < 0) {
dev_err(dai->dev, "Failed to assign probe stream: %d\n", ret);
return ret;
}
sdev->extractor_stream_tag = ret;
return 0;
}
static 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 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);
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);
kfree(desc);
exit:
ret = sof_ipc_probe_deinit(sdev);
if (ret < 0)
dev_err(dai->dev, "Failed to deinit probe: %d\n", ret);
sdev->extractor_stream_tag = SOF_PROBE_INVALID_NODE_ID;
snd_compr_free_pages(cstream);
return snd_sof_probe_compr_free(sdev, cstream, dai);
}
static int sof_probe_compr_set_params(struct snd_compr_stream *cstream,
struct snd_compr_params *params,
struct snd_soc_dai *dai)
{
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component);
struct snd_compr_runtime *rtd = cstream->runtime;
int ret;
cstream->dma_buffer.dev.type = SNDRV_DMA_TYPE_DEV_SG;
cstream->dma_buffer.dev.dev = sdev->dev;
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);
if (ret < 0)
return ret;
ret = sof_ipc_probe_init(sdev, sdev->extractor_stream_tag,
rtd->dma_bytes);
if (ret < 0) {
dev_err(dai->dev, "Failed to init probe: %d\n", ret);
return ret;
}
return 0;
}
static 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);
return snd_sof_probe_compr_trigger(sdev, cstream, cmd, dai);
}
static 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);
return snd_sof_probe_compr_pointer(sdev, cstream, tstamp, dai);
}
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);
static int sof_probe_compr_copy(struct snd_soc_component *component,
struct snd_compr_stream *cstream,
char __user *buf, size_t count)
{
struct snd_compr_runtime *rtd = cstream->runtime;
unsigned int offset, n;
void *ptr;
int ret;
if (count > rtd->buffer_size)
count = rtd->buffer_size;
div_u64_rem(rtd->total_bytes_transferred, rtd->buffer_size, &offset);
ptr = rtd->dma_area + offset;
n = rtd->buffer_size - offset;
if (count < n) {
ret = copy_to_user(buf, ptr, count);
} else {
ret = copy_to_user(buf, ptr, n);
ret += copy_to_user(buf + n, rtd->dma_area, count - n);
}
if (ret)
return count - ret;
return count;
}
const struct snd_compress_ops sof_probe_compressed_ops = {
.copy = sof_probe_compr_copy,
};
EXPORT_SYMBOL(sof_probe_compressed_ops);
......@@ -3,15 +3,34 @@
* 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) 2019-2020 Intel Corporation. All rights reserved.
*
* Copyright(c) 2019-2021 Intel Corporation. All rights reserved.
* Author: Cezary Rojewski <cezary.rojewski@intel.com>
*/
#ifndef __SOF_COMPRESS_H
#define __SOF_COMPRESS_H
#ifndef __SOF_PROBES_H
#define __SOF_PROBES_H
#include <sound/compress_driver.h>
#include <sound/sof/header.h>
struct snd_sof_dev;
#define SOF_PROBE_INVALID_NODE_ID UINT_MAX
struct sof_probe_point_desc {
unsigned int buffer_id;
unsigned int purpose;
unsigned int stream_tag;
} __packed;
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);
extern struct snd_soc_cdai_ops sof_probe_compr_ops;
extern const struct snd_compress_ops sof_probe_compressed_ops;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment