diff mbox series

[v5,2/5] coresight: Add coresight QMI driver

Message ID 20250424115854.2328190-3-quic_jinlmao@quicinc.com
State New
Headers show
Series coresight: Add remote etm support | expand

Commit Message

Mao Jinlong April 24, 2025, 11:58 a.m. UTC
Coresight QMI driver uses QMI(Qualcomm Messaging Interface) interfaces
to communicate with remote subsystems. Driver gets the instance id and
service id from device tree node and init the QMI connections to remote
subsystems. Send request function is for other coresight drivers to
communicate with remote subsystems.

Signed-off-by: Mao Jinlong <quic_jinlmao@quicinc.com>
---
 drivers/hwtracing/coresight/Kconfig         |  12 ++
 drivers/hwtracing/coresight/Makefile        |   1 +
 drivers/hwtracing/coresight/coresight-qmi.c | 209 ++++++++++++++++++++
 drivers/hwtracing/coresight/coresight-qmi.h | 107 ++++++++++
 4 files changed, 329 insertions(+)
 create mode 100644 drivers/hwtracing/coresight/coresight-qmi.c
 create mode 100644 drivers/hwtracing/coresight/coresight-qmi.h

Comments

kernel test robot April 26, 2025, 5:18 a.m. UTC | #1
Hi Mao,

kernel test robot noticed the following build warnings:

[auto build test WARNING on robh/for-next]
[also build test WARNING on linus/master v6.15-rc3 next-20250424]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Mao-Jinlong/dt-bindings-arm-Add-CoreSight-QMI-component-description/20250424-200202
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
patch link:    https://lore.kernel.org/r/20250424115854.2328190-3-quic_jinlmao%40quicinc.com
patch subject: [PATCH v5 2/5] coresight: Add coresight QMI driver
config: arm64-kismet-CONFIG_QCOM_QMI_HELPERS-CONFIG_CORESIGHT_QMI-0-0 (https://download.01.org/0day-ci/archive/20250426/202504261305.WCDIwfd5-lkp@intel.com/config)
reproduce: (https://download.01.org/0day-ci/archive/20250426/202504261305.WCDIwfd5-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202504261305.WCDIwfd5-lkp@intel.com/

kismet warnings: (new ones prefixed by >>)
>> kismet: WARNING: unmet direct dependencies detected for QCOM_QMI_HELPERS when selected by CORESIGHT_QMI
   WARNING: unmet direct dependencies detected for QCOM_QMI_HELPERS
     Depends on [n]: NET [=n]
     Selected by [y]:
     - CORESIGHT_QMI [=y] && CORESIGHT [=y]
diff mbox series

Patch

diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
index 06f0a7594169..61f673dbc2e9 100644
--- a/drivers/hwtracing/coresight/Kconfig
+++ b/drivers/hwtracing/coresight/Kconfig
@@ -247,4 +247,16 @@  config CORESIGHT_DUMMY
 
 	  To compile this driver as a module, choose M here: the module will be
 	  called coresight-dummy.
+
+config CORESIGHT_QMI
+	tristate "CORESIGHT QMI support"
+	select QCOM_QMI_HELPERS
+	help
+	  Enables support for sending command to subsystem via QMI. This is
+	  primarily used for sending QMI message to subsystems for remote trace
+	  sources.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called coresight-qmi.
+
 endif
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index 4ba478211b31..99ee0f8c25d2 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -50,4 +50,5 @@  obj-$(CONFIG_CORESIGHT_TPDA) += coresight-tpda.o
 coresight-cti-y := coresight-cti-core.o	coresight-cti-platform.o \
 		   coresight-cti-sysfs.o
 obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
+obj-$(CONFIG_CORESIGHT_QMI) += coresight-qmi.o
 obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
diff --git a/drivers/hwtracing/coresight/coresight-qmi.c b/drivers/hwtracing/coresight/coresight-qmi.c
new file mode 100644
index 000000000000..d93b606e7108
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-qmi.c
@@ -0,0 +1,209 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/coresight.h>
+
+#include "coresight-qmi.h"
+static LIST_HEAD(qmi_data);
+
+static int service_coresight_qmi_new_server(struct qmi_handle *qmi,
+		struct qmi_service *svc)
+{
+	struct qmi_data *data = container_of(qmi,
+					struct qmi_data, handle);
+
+	data->s_addr.sq_family = AF_QIPCRTR;
+	data->s_addr.sq_node = svc->node;
+	data->s_addr.sq_port = svc->port;
+	data->service_connected = true;
+	pr_debug("Connection established between QMI handle and %d service\n",
+		data->qmi_id);
+
+	return 0;
+}
+
+static void service_coresight_qmi_del_server(struct qmi_handle *qmi,
+		struct qmi_service *svc)
+{
+	struct qmi_data *data = container_of(qmi,
+					struct qmi_data, handle);
+	data->service_connected = false;
+	pr_debug("Connection disconnected between QMI handle and %d service\n",
+		data->qmi_id);
+}
+
+static struct qmi_ops server_ops = {
+	.new_server = service_coresight_qmi_new_server,
+	.del_server = service_coresight_qmi_del_server,
+};
+
+static int coresight_qmi_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *node = pdev->dev.of_node;
+	struct device_node *child_node;
+	int ret;
+
+	/**
+	 * Get the instance id and service id of the QMI service connection
+	 * from DT node. Creates QMI handle and register new lookup for each
+	 * QMI connection.
+	 */
+	for_each_available_child_of_node(node, child_node) {
+		struct qmi_data *data;
+
+		data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+		if (!data)
+			return -ENOMEM;
+
+		ret = of_property_read_u32(child_node, "qmi-id", &data->qmi_id);
+		if (ret)
+			return ret;
+
+		ret = of_property_read_u32(child_node, "service-id", &data->service_id);
+		if (ret)
+			return ret;
+
+		ret = qmi_handle_init(&data->handle,
+				CORESIGHT_QMI_MAX_MSG_LEN,
+				&server_ops, NULL);
+		if (ret < 0) {
+			dev_err(dev, "qmi client init failed ret:%d\n", ret);
+			return ret;
+		}
+
+		qmi_add_lookup(&data->handle,
+				data->service_id,
+				CORESIGHT_QMI_VERSION,
+				data->qmi_id);
+
+		list_add(&data->node, &qmi_data);
+	}
+
+	return 0;
+}
+
+/**
+ * coresight_get_qmi_data() - Get the qmi data struct from qmi_data
+ * @id:	instance id to get the qmi data
+ *
+ * Return: qmi data struct on success, NULL on failure.
+ */
+static struct qmi_data *coresight_get_qmi_data(int id)
+{
+	struct qmi_data *data;
+
+	list_for_each_entry(data, &qmi_data, node) {
+		if (data->qmi_id == id)
+			return data;
+	}
+
+	return NULL;
+}
+
+/**
+ * coresight_send_qmi_request() - Send a QMI message to remote subsystem
+ * @instance_id:	QMI Instance id of the remote subsystem
+ * @msg_id:	message id of the request
+ * @resp_ei:	description of how to decode a matching response
+ * @req_ei:	description of how to encode a matching request
+ * @resp:	pointer to the object to decode the response info
+ * @req:	pointer to the object to encode the request info
+ * @len:	max length of the QMI message
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+int coresight_send_qmi_request(int instance_id, int msg_id, struct qmi_elem_info *resp_ei,
+			struct qmi_elem_info *req_ei, void *resp, void *req, int len)
+{
+	struct qmi_txn txn;
+	int ret;
+	struct qmi_data *data;
+
+	data = coresight_get_qmi_data(instance_id);
+	if (!data) {
+		pr_err("No QMI data for QMI service!\n");
+		ret = -EINVAL;
+		return ret;
+	}
+
+	if (!data->service_connected) {
+		pr_err("QMI service not connected!\n");
+		ret = -EINVAL;
+		return ret;
+	}
+
+	ret = qmi_txn_init(&data->handle, &txn,
+			resp_ei,
+			resp);
+
+	if (ret < 0) {
+		pr_err("QMI tx init failed , ret:%d\n", ret);
+		return ret;
+	}
+
+	ret = qmi_send_request(&data->handle, &data->s_addr,
+			&txn, msg_id,
+			len,
+			req_ei,
+			req);
+
+	if (ret < 0) {
+		pr_err("QMI send ACK failed, ret:%d\n", ret);
+		qmi_txn_cancel(&txn);
+		return ret;
+	}
+
+	ret = qmi_txn_wait(&txn, msecs_to_jiffies(TIMEOUT_MS));
+	if (ret < 0) {
+		pr_err("QMI qmi txn wait failed, ret:%d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(coresight_send_qmi_request);
+
+static void coresight_qmi_remove(struct platform_device *pdev)
+{
+	struct qmi_data *data;
+
+	list_for_each_entry(data, &qmi_data, node) {
+		qmi_handle_release(&data->handle);
+	}
+}
+
+static const struct of_device_id coresight_qmi_match[] = {
+	{.compatible = "qcom,coresight-qmi"},
+	{}
+};
+
+static struct platform_driver coresight_qmi_driver = {
+	.probe          = coresight_qmi_probe,
+	.remove         = coresight_qmi_remove,
+	.driver         = {
+		.name   = "coresight-qmi",
+		.of_match_table = coresight_qmi_match,
+	},
+};
+
+static int __init coresight_qmi_init(void)
+{
+	return platform_driver_register(&coresight_qmi_driver);
+}
+module_init(coresight_qmi_init);
+
+static void __exit coresight_qmi_exit(void)
+{
+	platform_driver_unregister(&coresight_qmi_driver);
+}
+module_exit(coresight_qmi_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("CoreSight QMI driver");
diff --git a/drivers/hwtracing/coresight/coresight-qmi.h b/drivers/hwtracing/coresight/coresight-qmi.h
new file mode 100644
index 000000000000..1d57e46177b8
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-qmi.h
@@ -0,0 +1,107 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+#ifndef _CORESIGHT_QMI_H
+#define _CORESIGHT_QMI_H
+
+#include <linux/soc/qcom/qmi.h>
+
+#define CORESIGHT_QMI_VERSION			(1)
+
+#define CORESIGHT_QMI_SET_ETM_REQ_V01		(0x002C)
+#define CORESIGHT_QMI_SET_ETM_RESP_V01		(0x002C)
+
+#define CORESIGHT_QMI_MAX_MSG_LEN (50)
+
+#define TIMEOUT_MS				(10000)
+
+/* Qmi data for the QMI connection */
+struct qmi_data {
+	u32			qmi_id;
+	u32			service_id;
+	struct list_head	node;
+	struct qmi_handle	handle;
+	bool			service_connected;
+	struct sockaddr_qrtr	s_addr;
+};
+
+/**
+ * QMI service IDs
+ *
+ * CORESIGHT_QMI_QDSSC_SVC_ID for remote etm
+ * CORESIGHT_QMI_QDCP_SVC_ID for STM/TPDM/CTI
+ */
+enum coresight_qmi_service_id {
+	CORESIGHT_QMI_QDSSC_SVC_ID = 0x33,
+	CORESIGHT_QMI_QDCP_SVC_ID = 0xff,
+};
+
+enum coresight_qmi_instance_id {
+	CORESIGHT_QMI_INSTANCE_MODEM_V01 = 2,
+	CORESIGHT_QMI_INSTANCE_WLAN_V01 = 3,
+	CORESIGHT_QMI_INSTANCE_AOP_V01 = 4,
+	CORESIGHT_QMI_INSTANCE_ADSP_V01 = 5,
+	CORESIGHT_QMI_INSTANCE_VENUS_V01 = 6,
+	CORESIGHT_QMI_INSTANCE_GNSS_V01 = 7,
+	CORESIGHT_QMI_INSTANCE_SENSOR_V01 = 8,
+	CORESIGHT_QMI_INSTANCE_AUDIO_V01 = 9,
+	CORESIGHT_QMI_INSTANCE_VPU_V01 = 10,
+	CORESIGHT_QMI_INSTANCE_MODEM2_V01 = 11,
+	CORESIGHT_QMI_INSTANCE_SENSOR2_V01 = 12,
+	CORESIGHT_QMI_INSTANCE_CDSP_V01 = 13,
+	CORESIGHT_QMI_INSTANCE_NPU_V01 = 14,
+	CORESIGHT_QMI_INSTANCE_CDSP_USER_V01 = 15,
+	CORESIGHT_QMI_INSTANCE_CDSP1_V01 = 16,
+	CORESIGHT_QMI_INSTANCE_GPDSP0_V01 = 17,
+	CORESIGHT_QMI_INSTANCE_GPDSP1_V01 = 18,
+	CORESIGHT_QMI_INSTANCE_TBD_V01 = 19,
+	CORESIGHT_QMI_INSTANCE_GPDSP0_AUDI0_V01 = 20,
+	CORESIGHT_QMI_INSTANCE_GPDSP1_AUDI0_V01 = 21,
+	CORESIGHT_QMI_INSTANCE_MODEM_OEM_V01 = 22,
+	CORESIGHT_QMI_INSTANCE_ADSP1_V01 = 23,
+	CORESIGHT_QMI_INSTANCE_ADSP1_AUDIO_V01 = 24,
+	CORESIGHT_QMI_INSTANCE_ADSP2_V01 = 25,
+	CORESIGHT_QMI_INSTANCE_ADSP2_AUDIO_V01 = 26,
+	CORESIGHT_QMI_INSTANCE_CDSP2_V01 = 27,
+	CORESIGHT_QMI_INSTANCE_CDSP3_V01 = 28,
+	CORESIGHT_QMI_INSTANCE_SOCCP_V01 = 29,
+	CORESIGHT_QMI_INSTANCE_QECP_V01 = 30,
+};
+
+enum coresight_etm_state_enum_type_v01 {
+	/* To force a 32 bit signed enum. Do not change or use */
+	CORESIGHT_ETM_STATE_ENUM_TYPE_MIN_ENUM_VAL_V01 = INT_MIN,
+	CORESIGHT_ETM_STATE_DISABLED_V01 = 0,
+	CORESIGHT_ETM_STATE_ENABLED_V01 = 1,
+	CORESIGHT_ETM_STATE_ENUM_TYPE_MAX_ENUM_VAL_01 = INT_MAX,
+};
+
+/**
+ * Set remote etm request message
+ *
+ * @state enable/disable state
+ */
+struct coresight_set_etm_req_msg_v01 {
+	enum coresight_etm_state_enum_type_v01 state;
+};
+
+/**
+ * Set remote etm response message
+ */
+struct coresight_set_etm_resp_msg_v01 {
+	struct qmi_response_type_v01 resp;
+};
+
+#if IS_ENABLED(CONFIG_CORESIGHT_QMI)
+extern int coresight_send_qmi_request(int instance_id, int msg_id,
+		struct qmi_elem_info *resp_ei,
+		struct qmi_elem_info *req_ei, void *resp, void *req, int len);
+#else
+
+static inline int coresight_send_qmi_request(int instance_id, int msg_id,
+		struct qmi_elem_info *resp_ei,
+		struct qmi_elem_info *req_ei, void *resp, void *req, int len) {return NULL; }
+#endif
+
+#endif