Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Probes ipc4 get config #5249

Open
wants to merge 5 commits into
base: topic/sof-dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/sound/sof/ipc4/header.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,10 +326,14 @@ struct sof_ipc4_base_module_cfg {
#define SOF_IPC4_MOD_INSTANCE_SHIFT 16
#define SOF_IPC4_MOD_INSTANCE_MASK GENMASK(23, 16)
#define SOF_IPC4_MOD_INSTANCE(x) ((x) << SOF_IPC4_MOD_INSTANCE_SHIFT)
#define SOF_IPC4_MOD_INSTANCE_GET(x) (((x) & SOF_IPC4_MOD_INSTANCE_MASK) \
>> SOF_IPC4_MOD_INSTANCE_SHIFT)

#define SOF_IPC4_MOD_ID_SHIFT 0
#define SOF_IPC4_MOD_ID_MASK GENMASK(15, 0)
#define SOF_IPC4_MOD_ID(x) ((x) << SOF_IPC4_MOD_ID_SHIFT)
#define SOF_IPC4_MOD_ID_GET(x) (((x) & SOF_IPC4_MOD_ID_MASK) \
>> SOF_IPC4_MOD_ID_SHIFT)

/* init module ipc msg */
#define SOF_IPC4_MOD_EXT_PARAM_SIZE_SHIFT 0
Expand Down
25 changes: 18 additions & 7 deletions sound/soc/sof/sof-client-probes-ipc3.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,11 @@ static int ipc3_probes_deinit(struct sof_client_dev *cdev)
}

static int ipc3_probes_info(struct sof_client_dev *cdev, unsigned int cmd,
void **params, size_t *num_params)
void **params, size_t *num_params,
enum sof_probe_info_type type)
{
size_t max_msg_size = sof_client_get_ipc_max_payload_size(cdev);
struct device *dev = &cdev->auxdev.dev;
struct sof_ipc_probe_info_params msg = {{{0}}};
struct sof_ipc_probe_info_params *reply;
size_t bytes;
Expand All @@ -111,6 +113,11 @@ static int ipc3_probes_info(struct sof_client_dev *cdev, unsigned int cmd,
*params = NULL;
*num_params = 0;

if (type != PROBES_INFO_ACTIVE_PROBES) {
Copy link
Author

@jsarha jsarha Nov 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ujfalusi its checked here that we only handle active probes request for ipc3, but there is no technical issue stopping us from implementing the "available" request in the FW for ipc3 and allowing it here.

dev_err(dev, "%s: info type %u not supported", __func__, type);
return -EOPNOTSUPP;
}

reply = kzalloc(max_msg_size, GFP_KERNEL);
if (!reply)
return -ENOMEM;
Expand Down Expand Up @@ -142,21 +149,25 @@ static int ipc3_probes_info(struct sof_client_dev *cdev, unsigned int cmd,
}

/**
* ipc3_probes_points_info - retrieve list of active probe points
* ipc3_probes_points_info - retrieve list of probe points
* @cdev: SOF client device
* @desc: Returned list of active probes
* @num_desc: Returned count of active probes
* @type: Either PROBES_INFO_ACTIVE_PROBES or PROBES_INFO_AVAILABE_PROBES
*
* If type is PROBES_INFO_ACTIVE_PROBES, host sends PROBE_POINT_INFO
* request to obtain list of active probe points, valid for
* disconnection when given probe is no longer required.
*
* Host sends PROBE_POINT_INFO request to obtain list of active probe
* points, valid for disconnection when given probe is no longer
* required.
* Type PROBES_INFO_AVAILABE_PROBES is not yet supported.
*/
static int ipc3_probes_points_info(struct sof_client_dev *cdev,
struct sof_probe_point_desc **desc,
size_t *num_desc)
size_t *num_desc,
enum sof_probe_info_type type)
{
return ipc3_probes_info(cdev, SOF_IPC_PROBE_POINT_INFO,
(void **)desc, num_desc);
(void **)desc, num_desc, type);
}

/**
Expand Down
137 changes: 130 additions & 7 deletions sound/soc/sof/sof-client-probes-ipc4.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <sound/soc.h>
#include <sound/sof/ipc4/header.h>
#include <uapi/sound/sof/header.h>
#include "sof-audio.h"
#include "sof-priv.h"
#include "ipc4-priv.h"
#include "sof-client.h"
Expand All @@ -28,6 +29,7 @@ enum sof_ipc4_probe_runtime_param {
SOF_IPC4_PROBE_INJECTION_DMA_DETACH,
SOF_IPC4_PROBE_POINTS,
SOF_IPC4_PROBE_POINTS_DISCONNECT,
SOF_IPC4_PROBE_POINTS_AVAILABLE,
};

struct sof_ipc4_probe_gtw_cfg {
Expand All @@ -49,14 +51,42 @@ enum sof_ipc4_probe_type {
SOF_IPC4_PROBE_TYPE_INTERNAL
};

#define SOF_IPC4_PROBE_TYPE_SHIFT 24
#define SOF_IPC4_PROBE_TYPE_MASK GENMASK(25, 24)
#define SOF_IPC4_PROBE_TYPE_GET(x) (((x) & SOF_IPC4_PROBE_TYPE_MASK) \
>> SOF_IPC4_PROBE_TYPE_SHIFT)
#define SOF_IPC4_PROBE_IDX_SHIFT 26
#define SOF_IPC4_PROBE_IDX_MASK GENMASK(31, 26)
#define SOF_IPC4_PROBE_IDX_GET(x) (((x) & SOF_IPC4_PROBE_IDX_MASK) \
>> SOF_IPC4_PROBE_IDX_SHIFT)

struct sof_ipc4_probe_point {
u32 point_id;
u32 purpose;
u32 stream_tag;
} __packed __aligned(4);

struct sof_ipc4_probe_info {
unsigned int num_elems;
DECLARE_FLEX_ARRAY(struct sof_ipc4_probe_point, points);
} __packed;

#define INVALID_PIPELINE_ID 0xFF

static const char *sof_probe_ipc4_type_string(u32 type)
{
switch (type) {
case SOF_IPC4_PROBE_TYPE_INPUT:
return "input";
case SOF_IPC4_PROBE_TYPE_OUTPUT:
return "output";
case SOF_IPC4_PROBE_TYPE_INTERNAL:
return "internal";
default:
return "UNKNOWN";
}
}

/**
* sof_ipc4_probe_get_module_info - Get IPC4 module info for probe module
* @cdev: SOF client device
Expand Down Expand Up @@ -164,24 +194,116 @@ static int ipc4_probes_deinit(struct sof_client_dev *cdev)
}

/**
* ipc4_probes_points_info - retrieve list of active probe points
* ipc4_probes_points_info - retrieve list of probe points
* @cdev: SOF client device
* @desc: Returned list of active probes
* @num_desc: Returned count of active probes
* @type: Either PROBES_INFO_ACTIVE_PROBES or PROBES_INFO_AVAILABE_PROBES
* @return: 0 on success, negative error code on error
*
* Dummy implementation returning empty list of probes.
* Returns list if active probe points if type is
* PROBES_INFO_ACTIVE_PROBES, or list of all available probe points if
* type is PROBES_INFO_AVAILABE_PROBES.
*/
static int ipc4_probes_points_info(struct sof_client_dev *cdev,
struct sof_probe_point_desc **desc,
size_t *num_desc)
size_t *num_desc,
enum sof_probe_info_type type)
{
/* TODO: Firmware side implementation needed first */
*desc = NULL;
*num_desc = 0;
struct sof_man4_module *mentry = sof_ipc4_probe_get_module_info(cdev);
struct device *dev = &cdev->auxdev.dev;
struct sof_ipc4_probe_info *info;
struct sof_ipc4_msg msg;
u32 param_id;
int i, ret;

if (!mentry)
return -ENODEV;

switch (type) {
case PROBES_INFO_ACTIVE_PROBES:
param_id = SOF_IPC4_PROBE_POINTS;
break;
case PROBES_INFO_AVAILABE_PROBES:
param_id = SOF_IPC4_PROBE_POINTS_AVAILABLE;
break;
default:
dev_err(dev, "%s: info type %u not supported", __func__, type);
return -EOPNOTSUPP;
};

msg.primary = mentry->id;
msg.primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST);
msg.primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG);

msg.extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(param_id);

msg.data_size = cdev->sdev->ipc->max_payload_size;
msg.data_ptr = kzalloc(msg.data_size, GFP_KERNEL);
if (!msg.data_ptr)
return -ENOMEM;

ret = sof_client_ipc_set_get_data(cdev, &msg, false);
if (ret) {
kfree(msg.data_ptr);
return ret;
}
info = msg.data_ptr;
*num_desc = info->num_elems;
dev_dbg(dev, "%s: got %zu probe points", __func__, *num_desc);
info = msg.data_ptr;

*desc = kzalloc(*num_desc * sizeof(*desc), GFP_KERNEL);
if (!*desc) {
kfree(msg.data_ptr);
return -ENOMEM;
}

for (i = 0; i < *num_desc; i++) {
(*desc)[i].buffer_id = info->points[i].point_id;
(*desc)[i].purpose = info->points[i].purpose;
(*desc)[i].stream_tag = info->points[i].stream_tag;
}
kfree(msg.data_ptr);

return 0;
}

/**
* ipc4_probes_point_print - Human readable print of probe point descriptor
* @cdev: SOF client device
* @buf: Buffer to print to
* @size: Available bytes in buffer
* @desc: Describes the probe point to print
* @return: Number of bytes printed or an error code (snprintf return value)
*/
static int ipc4_probes_point_print(struct sof_client_dev *cdev, char *buf, size_t size,
struct sof_probe_point_desc *desc)
{
struct device *dev = &cdev->auxdev.dev;
struct snd_sof_widget *swidget;
int ret;

swidget = sof_client_ipc4_find_swidget_by_id(cdev, SOF_IPC4_MOD_ID_GET(desc->buffer_id),
SOF_IPC4_MOD_INSTANCE_GET(desc->buffer_id));
if (!swidget) {
dev_err(dev, "%s: Failed to find widget for module %lu.%lu\n",
__func__, SOF_IPC4_MOD_ID_GET(desc->buffer_id),
SOF_IPC4_MOD_INSTANCE_GET(desc->buffer_id));
ret = snprintf(buf, size, "%u,%u,%u\nUNKNOWN buffer_id 0x%08x\n",
desc->buffer_id, desc->purpose, desc->stream_tag,
desc->buffer_id);
return ret;
}

ret = snprintf(buf, size, "%u,%u,%u\t%s %s buf idx %lu %s\n",
desc->buffer_id, desc->purpose, desc->stream_tag, swidget->widget->name,
sof_probe_ipc4_type_string(SOF_IPC4_PROBE_TYPE_GET(desc->buffer_id)),
SOF_IPC4_PROBE_IDX_GET(desc->buffer_id),
desc->stream_tag ? "(connected)" : "");
return ret;
}

/**
* ipc4_probes_points_add - connect specified probes
* @cdev: SOF client device
Expand All @@ -202,7 +324,7 @@ static int ipc4_probes_points_add(struct sof_client_dev *cdev,
int i, ret;

if (!mentry)
return -ENODEV;
return -EOPNOTSUPP;

/* The sof_probe_point_desc and sof_ipc4_probe_point structs
* are of same size and even the integers are the same in the
Expand Down Expand Up @@ -286,6 +408,7 @@ const struct sof_probes_ipc_ops ipc4_probe_ops = {
.init = ipc4_probes_init,
.deinit = ipc4_probes_deinit,
.points_info = ipc4_probes_points_info,
.point_print = ipc4_probes_point_print,
.points_add = ipc4_probes_points_add,
.points_remove = ipc4_probes_points_remove,
};
58 changes: 49 additions & 9 deletions sound/soc/sof/sof-client-probes.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,14 @@

#include <sound/soc.h>
#include <sound/sof/header.h>
#include <sound/sof/ipc4/header.h>
#include "sof-client.h"
#include "sof-client-probes.h"
#include "sof-audio.h"

#ifdef CONFIG_SND_SOC_SOF_IPC4
#include "ipc4-priv.h"
#endif

#define SOF_PROBES_SUSPEND_DELAY_MS 3000
/* only extraction supported for now */
Expand Down Expand Up @@ -69,7 +75,8 @@ static int sof_probes_compr_shutdown(struct snd_compr_stream *cstream,
int i, ret;

/* disconnect all probe points */
ret = ipc->points_info(cdev, &desc, &num_desc);
ret = ipc->points_info(cdev, &desc, &num_desc,
PROBES_INFO_ACTIVE_PROBES);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hrm, so this will introduce an error print with IPC3 as the ACTIVE_PROBES is handled as error in there?

With IPC3 we don't have distinction between active or available probes, right? Both case should be handled in a similar way, provide all the probes.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. The active probes is the old feature that is supported also by ipc3. The available probes, giving all connection points availbale, is the new feature that is not supperted by ipc3. E.g. this call is equivalent to the old function that did not have the type argument.

If somebody tries to read "probe_points_available" in ipc3 system, then this funcion is called with PROBES_INFO_AVAILABLE_PROBES, and there will be a read error due to an ipc error. Then again nothing, but the lack of time, is stopping us from implementing available probes query for ipc3 too.

if (ret < 0) {
dev_err(dai->dev, "Failed to get probe points: %d\n", ret);
goto exit;
Expand Down Expand Up @@ -189,7 +196,8 @@ static const struct snd_compress_ops sof_probes_compressed_ops = {
};

static ssize_t sof_probes_dfs_points_read(struct file *file, char __user *to,
size_t count, loff_t *ppos)
size_t count, loff_t *ppos,
enum sof_probe_info_type type)
{
struct sof_client_dev *cdev = file->private_data;
struct sof_probes_priv *priv = cdev->data;
Expand All @@ -216,16 +224,20 @@ static ssize_t sof_probes_dfs_points_read(struct file *file, char __user *to,
goto exit;
}

ret = ipc->points_info(cdev, &desc, &num_desc);
ret = ipc->points_info(cdev, &desc, &num_desc, type);
if (ret < 0)
goto pm_error;

for (i = 0; i < num_desc; i++) {
offset = strlen(buf);
remaining = PAGE_SIZE - offset;
ret = snprintf(buf + offset, remaining,
"Id: %#010x Purpose: %u Node id: %#x\n",
desc[i].buffer_id, desc[i].purpose, desc[i].stream_tag);
if (ipc->point_print)
ret = ipc->point_print(cdev, buf + offset, remaining, &desc[i]);
else
ret = snprintf(buf + offset, remaining,
"Id: %#010x Purpose: %u Node id: %#x\n",
desc[i].buffer_id, desc[i].purpose, desc[i].stream_tag);
jsarha marked this conversation as resolved.
Show resolved Hide resolved

if (ret < 0 || ret >= remaining) {
/* truncate the output buffer at the last full line */
buf[offset] = '\0';
Expand All @@ -248,6 +260,22 @@ static ssize_t sof_probes_dfs_points_read(struct file *file, char __user *to,
return ret;
}

static ssize_t sof_probes_dfs_active_points_read(struct file *file,
char __user *to,
size_t count, loff_t *ppos)
{
return sof_probes_dfs_points_read(file, to, count, ppos,
PROBES_INFO_ACTIVE_PROBES);
}

static ssize_t sof_probes_dfs_available_points_read(struct file *file,
char __user *to,
size_t count, loff_t *ppos)
{
return sof_probes_dfs_points_read(file, to, count, ppos,
PROBES_INFO_AVAILABE_PROBES);
}

static ssize_t
sof_probes_dfs_points_write(struct file *file, const char __user *from,
size_t count, loff_t *ppos)
Expand Down Expand Up @@ -298,15 +326,23 @@ sof_probes_dfs_points_write(struct file *file, const char __user *from,
return ret;
}

static const struct file_operations sof_probes_points_fops = {
static const struct file_operations sof_probes_active_points_fops = {
.open = simple_open,
.read = sof_probes_dfs_points_read,
.read = sof_probes_dfs_active_points_read,
.write = sof_probes_dfs_points_write,
.llseek = default_llseek,

.owner = THIS_MODULE,
};

static const struct file_operations sof_probes_available_points_fops = {
.open = simple_open,
.read = sof_probes_dfs_available_points_read,
.llseek = default_llseek,

.owner = THIS_MODULE,
};

static ssize_t
sof_probes_dfs_points_remove_write(struct file *file, const char __user *from,
size_t count, loff_t *ppos)
Expand Down Expand Up @@ -452,13 +488,17 @@ static int sof_probes_client_probe(struct auxiliary_device *auxdev,

/* create read-write probes_points debugfs entry */
priv->dfs_points = debugfs_create_file("probe_points", 0644, dfsroot,
cdev, &sof_probes_points_fops);
cdev, &sof_probes_active_points_fops);

/* create read-write probe_points_remove debugfs entry */
priv->dfs_points_remove = debugfs_create_file("probe_points_remove", 0644,
dfsroot, cdev,
&sof_probes_points_remove_fops);

/* create read-write probes_points debugfs entry */
priv->dfs_points = debugfs_create_file("probe_points_available", 0644, dfsroot,
cdev, &sof_probes_available_points_fops);

links = devm_kcalloc(dev, SOF_PROBES_NUM_DAI_LINKS, sizeof(*links), GFP_KERNEL);
cpus = devm_kcalloc(dev, SOF_PROBES_NUM_DAI_LINKS, sizeof(*cpus), GFP_KERNEL);
if (!links || !cpus) {
Expand Down
Loading
Loading