Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 292da084 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soc: qcom: remoteqdss: Implement the remaining message types"

parents 81cd6798 d7597f2c
Loading
Loading
Loading
Loading
+245 −33
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <soc/qcom/scm.h>
#include <linux/debugfs.h>
#include <linux/ratelimit.h>
#include <linux/dma-mapping.h>

#define REMOTEQDSS_FLAG_QUIET (BIT(0))

@@ -25,10 +26,10 @@ module_param_named(dbg_flags, remoteqdss_dbg_flags, ulong, 0644);
static struct dentry *remoteqdss_dir;

#define REMOTEQDSS_ERR(fmt, ...) \
	pr_err("%s: " fmt, __func__, ## __VA_ARGS__)
	pr_debug("%s: " fmt, __func__, ## __VA_ARGS__)

#define REMOTEQDSS_ERR_CALLER(fmt, ...) \
	pr_err("%pf: " fmt, __builtin_return_address(0), ## __VA_ARGS__)
	pr_debug("%pf: " fmt, __builtin_return_address(1), ## __VA_ARGS__)

struct qdss_msg_translation {
	u64 val;
@@ -42,12 +43,58 @@ struct qdss_msg_translation {
 * dir			Parent debugfs directory
 */
struct remoteqdss_data {
	u8 id;
	u64 sw_entity_group;
	u64 sw_event_group;
	uint32_t id;
	uint32_t sw_entity_group;
	uint32_t sw_event_group;
	struct dentry *dir;
};

static struct device dma_dev;

/* Allowed message formats */

enum remoteqdss_cmd_id {
	CMD_ID_QUERY_SWEVENT_TAG,
	CMD_ID_FILTER_SWTRACE_STATE,
	CMD_ID_QUERY_SWTRACE_STATE,
	CMD_ID_FILTER_SWEVENT,
	CMD_ID_QUERY_SWEVENT,
	CMD_ID_FILTER_SWENTITY,
	CMD_ID_QUERY_SWENTITY,
};

struct remoteqdss_header_fmt {
	uint32_t subsys_id;
	uint32_t cmd_id;
};

struct remoteqdss_filter_swtrace_state_fmt {
	struct remoteqdss_header_fmt h;
	uint32_t state;
};

struct remoteqdss_filter_swevent_fmt {
	struct remoteqdss_header_fmt h;
	uint32_t event_group;
	uint32_t event_mask;
};

struct remoteqdss_query_swevent_fmt {
	struct remoteqdss_header_fmt h;
	uint32_t event_group;
};

struct remoteqdss_filter_swentity_fmt {
	struct remoteqdss_header_fmt h;
	uint32_t entity_group;
	uint32_t entity_mask;
};

struct remoteqdss_query_swentity_fmt {
	struct remoteqdss_header_fmt h;
	uint32_t entity_group;
};

/* msgs is a null terminated array */
static void remoteqdss_err_translation(struct qdss_msg_translation *msgs,
								u64 err)
@@ -71,9 +118,8 @@ static void remoteqdss_err_translation(struct qdss_msg_translation *msgs,
	REMOTEQDSS_ERR_CALLER("Error 0x%llx\n", err);
}

/* SCM based devices */
#define SCM_FILTER_SWTRACE_ID (0x1)
#define SCM_QUERY_SWTRACE_ID  (0x2)
/* Shared across all remoteqdss scm functions */
#define SCM_CMD_ID (0x1)

/* Response Values */
#define SCM_CMD_FAIL		(0x80)
@@ -113,25 +159,45 @@ static void free_remoteqdss_data(struct remoteqdss_data *data)
	kfree(data);
}

static int remoteqdss_scm_query_swtrace(void *priv, u64 *val)
static int remoteqdss_do_scm_call(struct scm_desc *desc,
		dma_addr_t addr, size_t size)
{
	struct remoteqdss_data *data = priv;
	int ret;
	struct scm_desc desc;

	memset(&desc, 0, sizeof(desc));
	desc.args[0] = data->id;
	desc.arginfo = SCM_ARGS(1, SCM_VAL);
	memset(desc, 0, sizeof(*desc));
	desc->args[0] = dma_to_phys(NULL, addr);
	desc->args[1] = size;
	desc->arginfo = SCM_ARGS(2, SCM_RO, SCM_VAL);

	ret = scm_call2(
		SCM_SIP_FNID(SCM_SVC_QDSS, SCM_QUERY_SWTRACE_ID),
		&desc);
		SCM_SIP_FNID(SCM_SVC_QDSS, SCM_CMD_ID),
		desc);
	if (ret)
		return ret;

	remoteqdss_err_translation(remoteqdss_scm_msgs, desc.ret[0]);
	ret = desc.ret[0] ? -EINVAL : 0;
	remoteqdss_err_translation(remoteqdss_scm_msgs, desc->ret[0]);
	ret = desc->ret[0] ? -EINVAL : 0;
	return ret;
}

static int remoteqdss_scm_query_swtrace(void *priv, u64 *val)
{
	struct remoteqdss_data *data = priv;
	int ret;
	struct scm_desc desc;
	struct remoteqdss_header_fmt *fmt;
	dma_addr_t addr;

	fmt = dma_alloc_coherent(&dma_dev, sizeof(*fmt), &addr, GFP_KERNEL);
	if (!fmt)
		return -ENOMEM;
	fmt->subsys_id = data->id;
	fmt->cmd_id = CMD_ID_QUERY_SWTRACE_STATE;

	ret = remoteqdss_do_scm_call(&desc, addr, sizeof(*fmt));
	*val = desc.ret[1];

	dma_free_coherent(&dma_dev, sizeof(*fmt), fmt, addr);
	return ret;
}

@@ -140,26 +206,150 @@ static int remoteqdss_scm_filter_swtrace(void *priv, u64 val)
	struct remoteqdss_data *data = priv;
	int ret;
	struct scm_desc desc;
	struct remoteqdss_filter_swtrace_state_fmt *fmt;
	dma_addr_t addr;

	memset(&desc, 0, sizeof(desc));
	desc.args[0] = data->id;
	desc.args[1] = val;
	desc.arginfo = SCM_ARGS(2, SCM_VAL, SCM_VAL);
	fmt = dma_alloc_coherent(&dma_dev, sizeof(*fmt), &addr, GFP_KERNEL);
	if (!fmt)
		return -ENOMEM;
	fmt->h.subsys_id = data->id;
	fmt->h.cmd_id = CMD_ID_FILTER_SWTRACE_STATE;
	fmt->state = (uint32_t)val;

	ret = scm_call2(
		SCM_SIP_FNID(SCM_SVC_QDSS, SCM_FILTER_SWTRACE_ID),
		&desc);
	if (ret)
		return ret;
	ret = remoteqdss_do_scm_call(&desc, addr, sizeof(*fmt));

	remoteqdss_err_translation(remoteqdss_scm_msgs, desc.ret[0]);
	ret = desc.ret[0] ? -EINVAL : 0;
	dma_free_coherent(&dma_dev, sizeof(*fmt), fmt, addr);
	return ret;
}

DEFINE_SIMPLE_ATTRIBUTE(fops_sw_trace_output,
			remoteqdss_scm_query_swtrace,
			remoteqdss_scm_filter_swtrace,
			"%llu\n");
			"0x%llx\n");

static int remoteqdss_scm_query_tag(void *priv, u64 *val)
{
	struct remoteqdss_data *data = priv;
	int ret;
	struct scm_desc desc;
	struct remoteqdss_header_fmt *fmt;
	dma_addr_t addr;

	fmt = dma_alloc_coherent(&dma_dev, sizeof(*fmt), &addr, GFP_KERNEL);
	if (!fmt)
		return -ENOMEM;
	fmt->subsys_id = data->id;
	fmt->cmd_id = CMD_ID_QUERY_SWEVENT_TAG;

	ret = remoteqdss_do_scm_call(&desc, addr, sizeof(*fmt));
	*val = desc.ret[1];

	dma_free_coherent(&dma_dev, sizeof(*fmt), fmt, addr);
	return ret;
}

DEFINE_SIMPLE_ATTRIBUTE(fops_tag,
			remoteqdss_scm_query_tag,
			NULL,
			"0x%llx\n");

static int remoteqdss_scm_query_swevent(void *priv, u64 *val)
{
	struct remoteqdss_data *data = priv;
	int ret;
	struct scm_desc desc;
	struct remoteqdss_query_swevent_fmt *fmt;
	dma_addr_t addr;

	fmt = dma_alloc_coherent(&dma_dev, sizeof(*fmt), &addr, GFP_KERNEL);
	if (!fmt)
		return -ENOMEM;
	fmt->h.subsys_id = data->id;
	fmt->h.cmd_id = CMD_ID_QUERY_SWEVENT;
	fmt->event_group = data->sw_event_group;

	ret = remoteqdss_do_scm_call(&desc, addr, sizeof(*fmt));
	*val = desc.ret[1];

	dma_free_coherent(&dma_dev, sizeof(*fmt), fmt, addr);
	return ret;
}

static int remoteqdss_scm_filter_swevent(void *priv, u64 val)
{
	struct remoteqdss_data *data = priv;
	int ret;
	struct scm_desc desc;
	struct remoteqdss_filter_swevent_fmt *fmt;
	dma_addr_t addr;

	fmt = dma_alloc_coherent(&dma_dev, sizeof(*fmt), &addr, GFP_KERNEL);
	if (!fmt)
		return -ENOMEM;
	fmt->h.subsys_id = data->id;
	fmt->h.cmd_id = CMD_ID_FILTER_SWEVENT;
	fmt->event_group = data->sw_event_group;
	fmt->event_mask = (uint32_t)val;

	ret = remoteqdss_do_scm_call(&desc, addr, sizeof(*fmt));

	dma_free_coherent(&dma_dev, sizeof(*fmt), fmt, addr);
	return ret;
}

DEFINE_SIMPLE_ATTRIBUTE(fops_swevent,
			remoteqdss_scm_query_swevent,
			remoteqdss_scm_filter_swevent,
			"0x%llx\n");

static int remoteqdss_scm_query_swentity(void *priv, u64 *val)
{
	struct remoteqdss_data *data = priv;
	int ret;
	struct scm_desc desc;
	struct remoteqdss_query_swentity_fmt *fmt;
	dma_addr_t addr;

	fmt = dma_alloc_coherent(&dma_dev, sizeof(*fmt), &addr, GFP_KERNEL);
	if (!fmt)
		return -ENOMEM;
	fmt->h.subsys_id = data->id;
	fmt->h.cmd_id = CMD_ID_QUERY_SWENTITY;
	fmt->entity_group = data->sw_entity_group;

	ret = remoteqdss_do_scm_call(&desc, addr, sizeof(*fmt));
	*val = desc.ret[1];

	dma_free_coherent(&dma_dev, sizeof(*fmt), fmt, addr);
	return ret;
}

static int remoteqdss_scm_filter_swentity(void *priv, u64 val)
{
	struct remoteqdss_data *data = priv;
	int ret;
	struct scm_desc desc;
	struct remoteqdss_filter_swentity_fmt *fmt;
	dma_addr_t addr;

	fmt = dma_alloc_coherent(&dma_dev, sizeof(*fmt), &addr, GFP_KERNEL);
	if (!fmt)
		return -ENOMEM;
	fmt->h.subsys_id = data->id;
	fmt->h.cmd_id = CMD_ID_FILTER_SWENTITY;
	fmt->entity_group = data->sw_entity_group;
	fmt->entity_mask = (uint32_t)val;

	ret = remoteqdss_do_scm_call(&desc, addr, sizeof(*fmt));

	dma_free_coherent(&dma_dev, sizeof(*fmt), fmt, addr);
	return ret;
}

DEFINE_SIMPLE_ATTRIBUTE(fops_swentity,
			remoteqdss_scm_query_swentity,
			remoteqdss_scm_filter_swentity,
			"0x%llx\n");

static void __init enumerate_scm_devices(struct dentry *parent)
{
@@ -189,16 +379,31 @@ static void __init enumerate_scm_devices(struct dentry *parent)
	if (IS_ERR_OR_NULL(dentry))
		goto out;

	dentry = debugfs_create_u64("sw_entity_group", S_IRUGO | S_IWUSR,
	dentry = debugfs_create_u32("sw_entity_group", S_IRUGO | S_IWUSR,
			data->dir, &data->sw_entity_group);
	if (IS_ERR_OR_NULL(dentry))
		goto out;

	dentry = debugfs_create_u64("sw_event_group", S_IRUGO | S_IWUSR,
	dentry = debugfs_create_u32("sw_event_group", S_IRUGO | S_IWUSR,
			data->dir, &data->sw_event_group);
	if (IS_ERR_OR_NULL(dentry))
		goto out;

	dentry = debugfs_create_file("tag", S_IRUGO,
			data->dir, data, &fops_tag);
	if (IS_ERR_OR_NULL(dentry))
		goto out;

	dentry = debugfs_create_file("swevent", S_IRUGO | S_IWUSR,
			data->dir, data, &fops_swevent);
	if (IS_ERR_OR_NULL(dentry))
		goto out;

	dentry = debugfs_create_file("swentity", S_IRUGO | S_IWUSR,
			data->dir, data, &fops_swentity);
	if (IS_ERR_OR_NULL(dentry))
		goto out;

	return;

out:
@@ -209,6 +414,13 @@ out:
static int __init remoteqdss_init(void)
{
	unsigned long old_flags = remoteqdss_dbg_flags;
	int ret;

	/* Set up DMA */
	arch_setup_dma_ops(&dma_dev, 0, U64_MAX, NULL, false);
	ret = dma_coerce_mask_and_coherent(&dma_dev, DMA_BIT_MASK(64));
	if (ret)
		return ret;

	/*
	 * disable normal error messages while checking
@@ -225,4 +437,4 @@ static int __init remoteqdss_init(void)
	remoteqdss_dbg_flags = old_flags;
	return 0;
}
module_init(remoteqdss_init);
late_initcall(remoteqdss_init);