From e0c8597ffe779df5d1fc4b1d1421948a486c6696 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Sat, 16 Nov 2024 21:58:38 +0200 Subject: [PATCH] ASoC: SOF: sof-client-probes: Add available points_info(), IPC4 only Add another debugfs file, "probe_points_available", that shows all the available probe points in the SOF FW at the time of query. The probe points are there only when an active SOF stream exists in the system. However, the stream identifiers are persistent in the sense that the same probe point identifiers always appear with the same playback or capture command in the same system configuration. The output, when reading "probe_points_available", may look like this: 16777220,0,256 host-copier.0.playback output 1 buf idx 0 (probed) 6,0,256 gain.1.1 input buf idx 0 (probed) 16777222,0,0 gain.1.1 output buf idx 0 2,0,0 mixin.1.1 input buf idx 0 16777218,0,0 mixin.1.1 output buf idx 0 3,0,0 mixout.2.1 input buf idx 0 16777219,0,0 mixout.2.1 output buf idx 0 65542,0,0 gain.2.1 input 0 buf idx 0 16842758,0,0 gain.2.1 output buf idx 0 15,0,0 smart_amp.2.1 input buf idx 0 16777231,0,0 smart_amp.2.1 output buf idx 0 65540,0,0 dai-copier.SSP.NoCodec-0.playback input buf idx 0 The triplet at the beginning of a line can be copy-pasted as such to "probe_points" debugfs file for adding a probe point. The rest of the line tries to give human readable explanation of what this probe point is. Signed-off-by: Jyri Sarha --- sound/soc/sof/sof-client-probes-ipc3.c | 25 ++++++++++----- sound/soc/sof/sof-client-probes-ipc4.c | 28 ++++++++++++++--- sound/soc/sof/sof-client-probes.c | 42 ++++++++++++++++++++++---- sound/soc/sof/sof-client-probes.h | 7 ++++- 4 files changed, 84 insertions(+), 18 deletions(-) diff --git a/sound/soc/sof/sof-client-probes-ipc3.c b/sound/soc/sof/sof-client-probes-ipc3.c index 816df745c9afce..a78ec0954a6188 100644 --- a/sound/soc/sof/sof-client-probes-ipc3.c +++ b/sound/soc/sof/sof-client-probes-ipc3.c @@ -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; @@ -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) { + dev_err(dev, "%s: info type %u not supported", __func__, type); + return -EOPNOTSUPP; + } + reply = kzalloc(max_msg_size, GFP_KERNEL); if (!reply) return -ENOMEM; @@ -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); } /** diff --git a/sound/soc/sof/sof-client-probes-ipc4.c b/sound/soc/sof/sof-client-probes-ipc4.c index b666b616de75f9..01959d8d173447 100644 --- a/sound/soc/sof/sof-client-probes-ipc4.c +++ b/sound/soc/sof/sof-client-probes-ipc4.c @@ -29,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 { @@ -170,30 +171,49 @@ 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 + * + * 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) { 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(SOF_IPC4_PROBE_POINTS); + 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); @@ -281,7 +301,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 diff --git a/sound/soc/sof/sof-client-probes.c b/sound/soc/sof/sof-client-probes.c index dcd0c075668540..bfde74badc0613 100644 --- a/sound/soc/sof/sof-client-probes.c +++ b/sound/soc/sof/sof-client-probes.c @@ -75,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); if (ret < 0) { dev_err(dai->dev, "Failed to get probe points: %d\n", ret); goto exit; @@ -195,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; @@ -222,7 +224,7 @@ 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; @@ -258,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) @@ -308,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) @@ -462,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) { diff --git a/sound/soc/sof/sof-client-probes.h b/sound/soc/sof/sof-client-probes.h index dc76b7114d4475..5a3f3260c90896 100644 --- a/sound/soc/sof/sof-client-probes.h +++ b/sound/soc/sof/sof-client-probes.h @@ -48,13 +48,18 @@ struct sof_probe_point_desc { #define SOF_IPC4_PROBE_IDX_GET(x) (((x) & SOF_IPC4_PROBE_IDX_MASK) \ >> SOF_IPC4_PROBE_IDX_SHIFT) +enum sof_probe_info_type { + PROBES_INFO_ACTIVE_PROBES = 0, + PROBES_INFO_AVAILABE_PROBES, +}; + struct sof_probes_ipc_ops { int (*init)(struct sof_client_dev *cdev, u32 stream_tag, size_t buffer_size); int (*deinit)(struct sof_client_dev *cdev); int (*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); int (*point_print)(struct sof_client_dev *cdev, char *buf, size_t size, struct sof_probe_point_desc *desc); int (*points_add)(struct sof_client_dev *cdev,