coresight: unify remote processor etm drivers

Unify modem, wcn, rpm, audio processor ETM drivers into a single remote
processor ETM driver.

Change-Id: I143b19f3a7be65bb476f57da924be2572a7add6a
Signed-off-by: Shaoqing Liu <shaoqingliu@codeaurora.org>
Signed-off-by: Xiaogang Cui <xiaogang@codeaurora.org>
This commit is contained in:
Shaoqing Liu 2015-03-31 15:29:07 +08:00 committed by Gerrit - the friendly Code Review server
parent 02367d144e
commit 6493f0d2da
23 changed files with 90 additions and 1286 deletions

View File

@ -28,23 +28,14 @@ Required properties:
"arm,coresight-fuse" for coresight fuse v1 device,
"arm,coresight-fuse-v2" for coresight fuse v2 device,
"arm,coresight-fuse-v3" for coresight fuse v3 device,
"qcom,coresight-audio-etm" for coresight audio etm trace device,
"qcom,coresight-modem-etm" for coresight modem etm trace device,
"qcom,coresight-wcn-etm" for coresight wireless etm trace device,
"qcom,coresight-rpm-etm" for coresight rpm etm trace device,
"qcom,coresight-remote-etm" for coresight remote processor etm trace device,
"qcom,coresight-qpdi" for coresight qpdi device
- reg : physical base address and length of the register set(s) of the component.
Not required for the following compatible strings:
- "qcom,coresight-audio-etm",
- "qcom,coresight-modem-etm",
- "qcom,coresight-wcn-etm",
- "qcom,coresight-rpm-etm"
Not required for the following compatible string:
- "qcom,coresight-remote-etm"
- reg-names : names corresponding to each reg property value.
Not required for the following compatible strings:
- "qcom,coresight-audio-etm",
- "qcom,coresight-modem-etm",
- "qcom,coresight-wcn-etm",
- "qcom,coresight-rpm-etm"
Not required for the following compatible string:
- "qcom,coresight-remote-etm"
The reg-names that need to be used with corresponding compatible string
for a coresight device are:
- for coresight tmc-etr or tmc-etf device:
@ -119,6 +110,7 @@ Required properties:
- coresight-id : unique integer identifier for the component
- coresight-name : unique descriptive name of the component
- coresight-nr-inports : number of input ports on the component
- qcom,inst-id : QMI instance id for remote ETMs
- coresight-cti-cpu : cpu phandle for cpu cti, required when qcom,cti-save is true
- coresight-etm-cpu : specifies phandle for the cpu associated with the ETM device
- qcom,dbgui-addr-offset : indicates the offset of dbgui address registers
@ -215,7 +207,6 @@ Optional properties:
connected to the aggregator on each port. Should be specified
in pairs (port, cmb element size).
- qcom,tpda-atid : specifies the ATID for TPDA.
-qcom,inst-id : QMI instance id for remote ETMs.
Examples:

View File

@ -410,10 +410,7 @@ CONFIG_CORESIGHT_REPLICATOR=y
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETM=y
CONFIG_CORESIGHT_AUDIO_ETM=y
CONFIG_CORESIGHT_MODEM_ETM=y
CONFIG_CORESIGHT_WCN_ETM=y
CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_REMOTE_ETM=y
CONFIG_SENSORS_SSC=y
CONFIG_MSM_BAM_DMUX=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y

View File

@ -560,8 +560,7 @@ CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETM=y
CONFIG_CORESIGHT_ETM_PCSAVE_DEFAULT_ENABLE=y
CONFIG_CORESIGHT_AUDIO_ETM=y
CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_REMOTE_ETM=y
CONFIG_SENSORS_SSC=y
CONFIG_PHY_MSM_SATA=y
CONFIG_MSM_EVENT_TIMER=y

View File

@ -322,9 +322,7 @@ CONFIG_CORESIGHT_REPLICATOR=y
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETM=y
CONFIG_CORESIGHT_AUDIO_ETM=y
CONFIG_CORESIGHT_MODEM_ETM=y
CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_REMOTE_ETM=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
CONFIG_MSM_QMI_INTERFACE=y
CONFIG_MSM_SMD=y

View File

@ -318,8 +318,7 @@ CONFIG_CORESIGHT_REPLICATOR=y
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETM=y
CONFIG_CORESIGHT_MODEM_ETM=y
CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_REMOTE_ETM=y
CONFIG_CORESIGHT_QPDI=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
CONFIG_MSM_QMI_INTERFACE=y

View File

@ -318,8 +318,7 @@ CONFIG_CORESIGHT_REPLICATOR=y
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETM=y
CONFIG_CORESIGHT_MODEM_ETM=y
CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_REMOTE_ETM=y
CONFIG_CORESIGHT_QPDI=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
CONFIG_MSM_QMI_INTERFACE=y

View File

@ -369,9 +369,7 @@ CONFIG_CORESIGHT_REPLICATOR=y
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETMV4=y
CONFIG_CORESIGHT_MODEM_ETM=y
CONFIG_CORESIGHT_WCN_ETM=y
CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_REMOTE_ETM=y
CONFIG_CORESIGHT_QPDI=y
CONFIG_MSM_BAM_DMUX=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y

View File

@ -407,10 +407,7 @@ CONFIG_CORESIGHT_REPLICATOR=y
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETM=y
CONFIG_CORESIGHT_AUDIO_ETM=y
CONFIG_CORESIGHT_MODEM_ETM=y
CONFIG_CORESIGHT_WCN_ETM=y
CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_REMOTE_ETM=y
CONFIG_SENSORS_SSC=y
CONFIG_MSM_BAM_DMUX=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y

View File

@ -380,10 +380,7 @@ CONFIG_CORESIGHT_REPLICATOR=y
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETM=y
CONFIG_CORESIGHT_AUDIO_ETM=y
CONFIG_CORESIGHT_MODEM_ETM=y
CONFIG_CORESIGHT_WCN_ETM=y
CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_REMOTE_ETM=y
CONFIG_SENSORS=y
CONFIG_MSM_BAM_DMUX=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y

View File

@ -501,9 +501,7 @@ CONFIG_CORESIGHT_REPLICATOR=y
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETM=y
CONFIG_CORESIGHT_MODEM_ETM=y
CONFIG_CORESIGHT_WCN_ETM=y
CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_REMOTE_ETM=y
CONFIG_CORESIGHT_QPDI=y
CONFIG_CORESIGHT_DBGUI=y
CONFIG_MSM_BAM_DMUX=y

View File

@ -496,9 +496,7 @@ CONFIG_CORESIGHT_REPLICATOR=y
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETM=y
CONFIG_CORESIGHT_MODEM_ETM=y
CONFIG_CORESIGHT_WCN_ETM=y
CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_REMOTE_ETM=y
CONFIG_CORESIGHT_QPDI=y
CONFIG_CORESIGHT_DBGUI=y
CONFIG_MSM_BAM_DMUX=y

View File

@ -459,10 +459,7 @@ CONFIG_CORESIGHT_REPLICATOR=y
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETMV4=y
CONFIG_CORESIGHT_AUDIO_ETM=y
CONFIG_CORESIGHT_MODEM_ETM=y
CONFIG_CORESIGHT_WCN_ETM=y
CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_REMOTE_ETM=y
CONFIG_CORESIGHT_QPDI=y
CONFIG_CORESIGHT_DBGUI=y
CONFIG_SENSORS=y

View File

@ -492,10 +492,7 @@ CONFIG_CORESIGHT_REPLICATOR=y
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETMV4=y
CONFIG_CORESIGHT_AUDIO_ETM=y
CONFIG_CORESIGHT_MODEM_ETM=y
CONFIG_CORESIGHT_WCN_ETM=y
CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_REMOTE_ETM=y
CONFIG_CORESIGHT_QPDI=y
CONFIG_CORESIGHT_DBGUI=y
CONFIG_SENSORS=y

View File

@ -462,10 +462,7 @@ CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETM=y
CONFIG_CORESIGHT_ETM_PCSAVE_DEFAULT_ENABLE=y
CONFIG_CORESIGHT_AUDIO_ETM=y
CONFIG_CORESIGHT_MODEM_ETM=y
CONFIG_CORESIGHT_WCN_ETM=y
CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_REMOTE_ETM=y
CONFIG_BIF=y
CONFIG_BIF_QPNP=y
CONFIG_SENSORS_SSC=y

View File

@ -498,10 +498,7 @@ CONFIG_CORESIGHT_TPDM=y
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETMV4=y
CONFIG_CORESIGHT_AUDIO_ETM=y
CONFIG_CORESIGHT_MODEM_ETM=y
CONFIG_CORESIGHT_WCN_ETM=y
CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_REMOTE_ETM=y
CONFIG_SENSORS_SSC=y
CONFIG_GENERIC_PHY=y
CONFIG_CP_ACCESS64=y

View File

@ -490,11 +490,8 @@ CONFIG_CORESIGHT_REPLICATOR=y
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETMV4=y
CONFIG_CORESIGHT_AUDIO_ETM=y
CONFIG_CORESIGHT_MODEM_ETM=y
CONFIG_CORESIGHT_WCN_ETM=y
CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_DBGUI=y
CONFIG_CORESIGHT_REMOTE_ETM=y
CONFIG_SENSORS=y
CONFIG_SENSORS_SSC=y
CONFIG_CP_ACCESS64=y

View File

@ -233,70 +233,18 @@ config CORESIGHT_ETMV4_DEFAULT_ENABLE
If unsure, say 'N' here to avoid potential power and performance
penalty.
config CORESIGHT_AUDIO_ETM
bool "Audio processor ETM trace support"
config CORESIGHT_REMOTE_ETM
bool "Remote processor ETM trace support"
help
Enables support for ETM trace collection on audio processor using
CoreSight framework. Enabling this will allow turning on ETM tracing
on audio processor via sysfs by configuring the required CoreSight
components.
config CORESIGHT_AUDIO_ETM_DEFAULT_ENABLE
bool "Turn on audio processor ETM tracing by default"
help
Turns on CoreSight audio processor ETM tracing by default. Otherwise,
tracing is disabled by default but can be enabled via sysfs.
If unsure, say 'N' here to avoid potential power and performance
penalty.
config CORESIGHT_MODEM_ETM
bool "Modem processor ETM trace support"
help
Enables support for ETM trace collection on modem processor using
CoreSight framework. Enabling this will allow turning on ETM tracing
on modem processor via sysfs by configuring the required CoreSight
components.
config CORESIGHT_MODEM_ETM_DEFAULT_ENABLE
bool "Turn on modem processor ETM tracing by default"
help
Turns on CoreSight modem processor ETM tracing by default. Otherwise,
tracing is disabled by default but can be enabled via sysfs.
If unsure, say 'N' here to avoid potential power and performance
penalty.
config CORESIGHT_WCN_ETM
bool "Wireless subsystem processor ETM trace support"
help
Enables support for ETM trace collection on wireless subsystem
processor using CoreSight framework. Enabling this will allow
turning on ETM tracing on wireless subsystem via sysfs by configuring
the required CoreSight components.
config CORESIGHT_WCN_ETM_DEFAULT_ENABLE
bool "Turn on wireless subsystem processor ETM tracing by default"
help
Turns on CoreSight wireless subsystem processor ETM tracing by
default. Otherwise, tracing is disabled by default but can be enabled
via sysfs.
If unsure, say 'N' here to avoid potential power and performance
penalty.
config CORESIGHT_RPM_ETM
bool "RPM processor ETM trace support"
help
Enables support for ETM trace collection on RPM processor using
Enables support for ETM trace collection on remote processor using
CoreSight framework. Enabling this will allow turning on ETM
tracing on RPM processor via sysfs by configuring the required
tracing on remote processor via sysfs by configuring the required
CoreSight components.
config CORESIGHT_RPM_ETM_DEFAULT_ENABLE
bool "Turn on RPM processor ETM tracing by default"
config CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE
bool "Turn on remote processor ETM tracing by default"
help
Turns on CoreSight RPM processor ETM tracing by default. Otherwise,
Turns on CoreSight remote processor ETM tracing by default. Otherwise,
tracing is disabled by default but can be enabled via sysfs.
If unsure, say 'N' here to avoid potential power and performance

View File

@ -17,8 +17,5 @@ obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o
obj-$(CONFIG_CORESIGHT_HWEVENT) += coresight-hwevent.o
obj-$(CONFIG_CORESIGHT_ETM) += coresight-etm.o coresight-etm-cp14.o
obj-$(CONFIG_CORESIGHT_ETMV4) += coresight-etmv4.o
obj-$(CONFIG_CORESIGHT_AUDIO_ETM) += coresight-audio-etm.o
obj-$(CONFIG_CORESIGHT_MODEM_ETM) += coresight-modem-etm.o
obj-$(CONFIG_CORESIGHT_WCN_ETM) += coresight-wcn-etm.o
obj-$(CONFIG_CORESIGHT_RPM_ETM) += coresight-rpm-etm.o
obj-$(CONFIG_CORESIGHT_REMOTE_ETM) += coresight-remote-etm.o
obj-$(CONFIG_CORESIGHT_QPDI) += coresight-qpdi.o

View File

@ -1,363 +0,0 @@
/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/sysfs.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_coresight.h>
#include <linux/coresight.h>
#include "coresight-qmi.h"
#ifdef CONFIG_CORESIGHT_AUDIO_ETM_DEFAULT_ENABLE
static int boot_enable = 1;
#else
static int boot_enable;
#endif
module_param_named(
boot_enable, boot_enable, int, S_IRUGO
);
struct audio_etm_drvdata {
struct device *dev;
struct coresight_device *csdev;
struct mutex mutex;
struct workqueue_struct *wq;
struct qmi_handle *handle;
struct work_struct work_svc_arrive;
struct work_struct work_svc_exit;
struct work_struct work_rcv_msg;
struct notifier_block nb;
uint32_t inst_id;
};
static int audio_etm_enable(struct coresight_device *csdev)
{
struct audio_etm_drvdata *drvdata =
dev_get_drvdata(csdev->dev.parent);
struct coresight_set_etm_req_msg_v01 req;
struct coresight_set_etm_resp_msg_v01 resp = { { 0, 0 } };
struct msg_desc req_desc, resp_desc;
int ret;
mutex_lock(&drvdata->mutex);
/*
* The QMI handle may be NULL in the following scenarios:
* 1. QMI service is not present
* 2. QMI service is present but attempt to enable remote ETM is earlier
* than service is ready to handle request
* 3. Connection between QMI client and QMI service failed
*
* Enable CoreSight without processing further QMI commands which
* provides the option to enable remote ETM by other means.
*/
if (!drvdata->handle) {
dev_info(drvdata->dev,
"%s: QMI service unavailable. Skipping QMI requests\n",
__func__);
goto out;
}
req.state = CORESIGHT_ETM_STATE_ENABLED_V01;
req_desc.msg_id = CORESIGHT_QMI_SET_ETM_REQ_V01;
req_desc.max_msg_len = CORESIGHT_QMI_SET_ETM_REQ_MAX_LEN;
req_desc.ei_array = coresight_set_etm_req_msg_v01_ei;
resp_desc.msg_id = CORESIGHT_QMI_SET_ETM_RESP_V01;
resp_desc.max_msg_len = CORESIGHT_QMI_SET_ETM_RESP_MAX_LEN;
resp_desc.ei_array = coresight_set_etm_resp_msg_v01_ei;
ret = qmi_send_req_wait(drvdata->handle, &req_desc, &req, sizeof(req),
&resp_desc, &resp, sizeof(resp), TIMEOUT_MS);
if (ret < 0) {
dev_err(drvdata->dev, "%s: QMI send req failed %d\n", __func__,
ret);
goto err;
}
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
dev_err(drvdata->dev, "%s: QMI request failed %d %d\n",
__func__, resp.resp.result, resp.resp.error);
ret = -EREMOTEIO;
goto err;
}
out:
mutex_unlock(&drvdata->mutex);
dev_info(drvdata->dev, "Audio ETM tracing enabled\n");
return 0;
err:
mutex_unlock(&drvdata->mutex);
return ret;
}
static void audio_etm_disable(struct coresight_device *csdev)
{
struct audio_etm_drvdata *drvdata =
dev_get_drvdata(csdev->dev.parent);
struct coresight_set_etm_req_msg_v01 req;
struct coresight_set_etm_resp_msg_v01 resp = { { 0, 0 } };
struct msg_desc req_desc, resp_desc;
int ret;
mutex_lock(&drvdata->mutex);
if (!drvdata->handle) {
dev_info(drvdata->dev,
"%s: QMI service unavailable. Skipping QMI requests\n",
__func__);
goto out;
}
req.state = CORESIGHT_ETM_STATE_DISABLED_V01;
req_desc.msg_id = CORESIGHT_QMI_SET_ETM_REQ_V01;
req_desc.max_msg_len = CORESIGHT_QMI_SET_ETM_REQ_MAX_LEN;
req_desc.ei_array = coresight_set_etm_req_msg_v01_ei;
resp_desc.msg_id = CORESIGHT_QMI_SET_ETM_RESP_V01;
resp_desc.max_msg_len = CORESIGHT_QMI_SET_ETM_RESP_MAX_LEN;
resp_desc.ei_array = coresight_set_etm_resp_msg_v01_ei;
ret = qmi_send_req_wait(drvdata->handle, &req_desc, &req, sizeof(req),
&resp_desc, &resp, sizeof(resp), TIMEOUT_MS);
if (ret < 0) {
dev_err(drvdata->dev, "%s: QMI send req failed %d\n", __func__,
ret);
goto err;
}
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
dev_err(drvdata->dev, "%s: QMI request failed %d %d\n",
__func__, resp.resp.result, resp.resp.error);
goto err;
}
out:
mutex_unlock(&drvdata->mutex);
dev_info(drvdata->dev, "Audio ETM tracing disabled\n");
return;
err:
mutex_unlock(&drvdata->mutex);
}
static const struct coresight_ops_source audio_etm_source_ops = {
.enable = audio_etm_enable,
.disable = audio_etm_disable,
};
static const struct coresight_ops audio_cs_ops = {
.source_ops = &audio_etm_source_ops,
};
static void audio_etm_rcv_msg(struct work_struct *work)
{
struct audio_etm_drvdata *drvdata = container_of(work,
struct audio_etm_drvdata,
work_rcv_msg);
if (qmi_recv_msg(drvdata->handle) < 0)
dev_err(drvdata->dev, "%s: Error receiving QMI message\n",
__func__);
}
static void audio_etm_notify(struct qmi_handle *handle,
enum qmi_event_type event, void *notify_priv)
{
struct audio_etm_drvdata *drvdata =
(struct audio_etm_drvdata *)notify_priv;
switch (event) {
case QMI_RECV_MSG:
queue_work(drvdata->wq, &drvdata->work_rcv_msg);
break;
default:
break;
}
}
static void audio_etm_svc_arrive(struct work_struct *work)
{
struct audio_etm_drvdata *drvdata = container_of(work,
struct audio_etm_drvdata,
work_svc_arrive);
drvdata->handle = qmi_handle_create(audio_etm_notify, drvdata);
if (!drvdata->handle) {
dev_err(drvdata->dev, "%s: QMI client handle alloc failed\n",
__func__);
return;
}
if (qmi_connect_to_service(drvdata->handle, CORESIGHT_QMI_SVC_ID,
CORESIGHT_QMI_VERSION,
drvdata->inst_id) < 0) {
dev_err(drvdata->dev,
"%s: Could not connect handle to service\n", __func__);
qmi_handle_destroy(drvdata->handle);
drvdata->handle = NULL;
}
}
static void audio_etm_svc_exit(struct work_struct *work)
{
struct audio_etm_drvdata *drvdata = container_of(work,
struct audio_etm_drvdata,
work_svc_exit);
qmi_handle_destroy(drvdata->handle);
drvdata->handle = NULL;
}
static int audio_etm_svc_event_notify(struct notifier_block *this,
unsigned long event,
void *data)
{
struct audio_etm_drvdata *drvdata = container_of(this,
struct audio_etm_drvdata,
nb);
switch (event) {
case QMI_SERVER_ARRIVE:
queue_work(drvdata->wq, &drvdata->work_svc_arrive);
break;
case QMI_SERVER_EXIT:
queue_work(drvdata->wq, &drvdata->work_svc_exit);
break;
default:
break;
}
return 0;
}
static int audio_etm_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct coresight_platform_data *pdata;
struct audio_etm_drvdata *drvdata;
struct coresight_desc *desc;
int ret;
if (pdev->dev.of_node) {
pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
pdev->dev.platform_data = pdata;
}
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
drvdata->dev = &pdev->dev;
platform_set_drvdata(pdev, drvdata);
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
if (!desc)
return -ENOMEM;
if (pdev->dev.of_node) {
ret = of_property_read_u32(pdev->dev.of_node, "qcom,inst-id",
&drvdata->inst_id);
if (ret)
drvdata->inst_id = CORESIGHT_SVC_INST_ID_AUDIO_V01;
}
mutex_init(&drvdata->mutex);
drvdata->nb.notifier_call = audio_etm_svc_event_notify;
drvdata->wq = create_singlethread_workqueue("audio-etm");
if (!drvdata->wq)
return -EFAULT;
INIT_WORK(&drvdata->work_svc_arrive, audio_etm_svc_arrive);
INIT_WORK(&drvdata->work_svc_exit, audio_etm_svc_exit);
INIT_WORK(&drvdata->work_rcv_msg, audio_etm_rcv_msg);
ret = qmi_svc_event_notifier_register(CORESIGHT_QMI_SVC_ID,
CORESIGHT_QMI_VERSION,
drvdata->inst_id,
&drvdata->nb);
if (ret < 0)
goto err0;
desc->type = CORESIGHT_DEV_TYPE_SOURCE;
desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
desc->ops = &audio_cs_ops;
desc->pdata = pdev->dev.platform_data;
desc->dev = &pdev->dev;
desc->owner = THIS_MODULE;
drvdata->csdev = coresight_register(desc);
if (IS_ERR(drvdata->csdev)) {
ret = PTR_ERR(drvdata->csdev);
goto err1;
}
dev_info(dev, "Audio ETM initialized\n");
if (boot_enable)
coresight_enable(drvdata->csdev);
return 0;
err1:
qmi_svc_event_notifier_unregister(CORESIGHT_QMI_SVC_ID,
CORESIGHT_QMI_VERSION,
drvdata->inst_id,
&drvdata->nb);
err0:
destroy_workqueue(drvdata->wq);
return ret;
}
static int audio_etm_remove(struct platform_device *pdev)
{
struct audio_etm_drvdata *drvdata = platform_get_drvdata(pdev);
coresight_unregister(drvdata->csdev);
return 0;
}
static struct of_device_id audio_etm_match[] = {
{.compatible = "qcom,coresight-audio-etm"},
{}
};
static struct platform_driver audio_etm_driver = {
.probe = audio_etm_probe,
.remove = audio_etm_remove,
.driver = {
.name = "coresight-audio-etm",
.owner = THIS_MODULE,
.of_match_table = audio_etm_match,
},
};
int __init audio_etm_init(void)
{
return platform_driver_register(&audio_etm_driver);
}
module_init(audio_etm_init);
void __exit audio_etm_exit(void)
{
platform_driver_unregister(&audio_etm_driver);
}
module_exit(audio_etm_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("CoreSight Audio ETM driver");

View File

@ -1,363 +0,0 @@
/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/sysfs.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_coresight.h>
#include <linux/coresight.h>
#include "coresight-qmi.h"
#ifdef CONFIG_CORESIGHT_MODEM_ETM_DEFAULT_ENABLE
static int boot_enable = 1;
#else
static int boot_enable;
#endif
module_param_named(
boot_enable, boot_enable, int, S_IRUGO
);
struct modem_etm_drvdata {
struct device *dev;
struct coresight_device *csdev;
struct mutex mutex;
struct workqueue_struct *wq;
struct qmi_handle *handle;
struct work_struct work_svc_arrive;
struct work_struct work_svc_exit;
struct work_struct work_rcv_msg;
struct notifier_block nb;
uint32_t inst_id;
};
static int modem_etm_enable(struct coresight_device *csdev)
{
struct modem_etm_drvdata *drvdata =
dev_get_drvdata(csdev->dev.parent);
struct coresight_set_etm_req_msg_v01 req;
struct coresight_set_etm_resp_msg_v01 resp = { { 0, 0 } };
struct msg_desc req_desc, resp_desc;
int ret;
mutex_lock(&drvdata->mutex);
/*
* The QMI handle may be NULL in the following scenarios:
* 1. QMI service is not present
* 2. QMI service is present but attempt to enable remote ETM is earlier
* than service is ready to handle request
* 3. Connection between QMI client and QMI service failed
*
* Enable CoreSight without processing further QMI commands which
* provides the option to enable remote ETM by other means.
*/
if (!drvdata->handle) {
dev_info(drvdata->dev,
"%s: QMI service unavailable. Skipping QMI requests\n",
__func__);
goto out;
}
req.state = CORESIGHT_ETM_STATE_ENABLED_V01;
req_desc.msg_id = CORESIGHT_QMI_SET_ETM_REQ_V01;
req_desc.max_msg_len = CORESIGHT_QMI_SET_ETM_REQ_MAX_LEN;
req_desc.ei_array = coresight_set_etm_req_msg_v01_ei;
resp_desc.msg_id = CORESIGHT_QMI_SET_ETM_RESP_V01;
resp_desc.max_msg_len = CORESIGHT_QMI_SET_ETM_RESP_MAX_LEN;
resp_desc.ei_array = coresight_set_etm_resp_msg_v01_ei;
ret = qmi_send_req_wait(drvdata->handle, &req_desc, &req, sizeof(req),
&resp_desc, &resp, sizeof(resp), TIMEOUT_MS);
if (ret < 0) {
dev_err(drvdata->dev, "%s: QMI send req failed %d\n", __func__,
ret);
goto err;
}
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
dev_err(drvdata->dev, "%s: QMI request failed %d %d\n",
__func__, resp.resp.result, resp.resp.error);
ret = -EREMOTEIO;
goto err;
}
out:
mutex_unlock(&drvdata->mutex);
dev_info(drvdata->dev, "Modem ETM tracing enabled\n");
return 0;
err:
mutex_unlock(&drvdata->mutex);
return ret;
}
static void modem_etm_disable(struct coresight_device *csdev)
{
struct modem_etm_drvdata *drvdata =
dev_get_drvdata(csdev->dev.parent);
struct coresight_set_etm_req_msg_v01 req;
struct coresight_set_etm_resp_msg_v01 resp = { { 0, 0 } };
struct msg_desc req_desc, resp_desc;
int ret;
mutex_lock(&drvdata->mutex);
if (!drvdata->handle) {
dev_info(drvdata->dev,
"%s: QMI service unavailable. Skipping QMI requests\n",
__func__);
goto out;
}
req.state = CORESIGHT_ETM_STATE_DISABLED_V01;
req_desc.msg_id = CORESIGHT_QMI_SET_ETM_REQ_V01;
req_desc.max_msg_len = CORESIGHT_QMI_SET_ETM_REQ_MAX_LEN;
req_desc.ei_array = coresight_set_etm_req_msg_v01_ei;
resp_desc.msg_id = CORESIGHT_QMI_SET_ETM_RESP_V01;
resp_desc.max_msg_len = CORESIGHT_QMI_SET_ETM_RESP_MAX_LEN;
resp_desc.ei_array = coresight_set_etm_resp_msg_v01_ei;
ret = qmi_send_req_wait(drvdata->handle, &req_desc, &req, sizeof(req),
&resp_desc, &resp, sizeof(resp), TIMEOUT_MS);
if (ret < 0) {
dev_err(drvdata->dev, "%s: QMI send req failed %d\n", __func__,
ret);
goto err;
}
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
dev_err(drvdata->dev, "%s: QMI request failed %d %d\n",
__func__, resp.resp.result, resp.resp.error);
goto err;
}
out:
mutex_unlock(&drvdata->mutex);
dev_info(drvdata->dev, "Modem ETM tracing disabled\n");
return;
err:
mutex_unlock(&drvdata->mutex);
}
static const struct coresight_ops_source modem_etm_source_ops = {
.enable = modem_etm_enable,
.disable = modem_etm_disable,
};
static const struct coresight_ops modem_cs_ops = {
.source_ops = &modem_etm_source_ops,
};
static void modem_etm_rcv_msg(struct work_struct *work)
{
struct modem_etm_drvdata *drvdata = container_of(work,
struct modem_etm_drvdata,
work_rcv_msg);
if (qmi_recv_msg(drvdata->handle) < 0)
dev_err(drvdata->dev, "%s: Error receiving QMI message\n",
__func__);
}
static void modem_etm_notify(struct qmi_handle *handle,
enum qmi_event_type event, void *notify_priv)
{
struct modem_etm_drvdata *drvdata =
(struct modem_etm_drvdata *)notify_priv;
switch (event) {
case QMI_RECV_MSG:
queue_work(drvdata->wq, &drvdata->work_rcv_msg);
break;
default:
break;
}
}
static void modem_etm_svc_arrive(struct work_struct *work)
{
struct modem_etm_drvdata *drvdata = container_of(work,
struct modem_etm_drvdata,
work_svc_arrive);
drvdata->handle = qmi_handle_create(modem_etm_notify, drvdata);
if (!drvdata->handle) {
dev_err(drvdata->dev, "%s: QMI client handle alloc failed\n",
__func__);
return;
}
if (qmi_connect_to_service(drvdata->handle, CORESIGHT_QMI_SVC_ID,
CORESIGHT_QMI_VERSION,
drvdata->inst_id) < 0) {
dev_err(drvdata->dev,
"%s: Could not connect handle to service\n", __func__);
qmi_handle_destroy(drvdata->handle);
drvdata->handle = NULL;
}
}
static void modem_etm_svc_exit(struct work_struct *work)
{
struct modem_etm_drvdata *drvdata = container_of(work,
struct modem_etm_drvdata,
work_svc_exit);
qmi_handle_destroy(drvdata->handle);
drvdata->handle = NULL;
}
static int modem_etm_svc_event_notify(struct notifier_block *this,
unsigned long event,
void *data)
{
struct modem_etm_drvdata *drvdata = container_of(this,
struct modem_etm_drvdata,
nb);
switch (event) {
case QMI_SERVER_ARRIVE:
queue_work(drvdata->wq, &drvdata->work_svc_arrive);
break;
case QMI_SERVER_EXIT:
queue_work(drvdata->wq, &drvdata->work_svc_exit);
break;
default:
break;
}
return 0;
}
static int modem_etm_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct coresight_platform_data *pdata;
struct modem_etm_drvdata *drvdata;
struct coresight_desc *desc;
int ret;
if (pdev->dev.of_node) {
pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
pdev->dev.platform_data = pdata;
}
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
drvdata->dev = &pdev->dev;
platform_set_drvdata(pdev, drvdata);
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
if (!desc)
return -ENOMEM;
if (pdev->dev.of_node) {
ret = of_property_read_u32(pdev->dev.of_node, "qcom,inst-id",
&drvdata->inst_id);
if (ret)
drvdata->inst_id = CORESIGHT_SVC_INST_ID_MODEM_V01;
}
mutex_init(&drvdata->mutex);
drvdata->nb.notifier_call = modem_etm_svc_event_notify;
drvdata->wq = create_singlethread_workqueue("modem-etm");
if (!drvdata->wq)
return -EFAULT;
INIT_WORK(&drvdata->work_svc_arrive, modem_etm_svc_arrive);
INIT_WORK(&drvdata->work_svc_exit, modem_etm_svc_exit);
INIT_WORK(&drvdata->work_rcv_msg, modem_etm_rcv_msg);
ret = qmi_svc_event_notifier_register(CORESIGHT_QMI_SVC_ID,
CORESIGHT_QMI_VERSION,
drvdata->inst_id,
&drvdata->nb);
if (ret < 0)
goto err0;
desc->type = CORESIGHT_DEV_TYPE_SOURCE;
desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
desc->ops = &modem_cs_ops;
desc->pdata = pdev->dev.platform_data;
desc->dev = &pdev->dev;
desc->owner = THIS_MODULE;
drvdata->csdev = coresight_register(desc);
if (IS_ERR(drvdata->csdev)) {
ret = PTR_ERR(drvdata->csdev);
goto err1;
}
dev_info(dev, "Modem ETM initialized\n");
if (boot_enable)
coresight_enable(drvdata->csdev);
return 0;
err1:
qmi_svc_event_notifier_unregister(CORESIGHT_QMI_SVC_ID,
CORESIGHT_QMI_VERSION,
drvdata->inst_id,
&drvdata->nb);
err0:
destroy_workqueue(drvdata->wq);
return ret;
}
static int modem_etm_remove(struct platform_device *pdev)
{
struct modem_etm_drvdata *drvdata = platform_get_drvdata(pdev);
coresight_unregister(drvdata->csdev);
return 0;
}
static struct of_device_id modem_etm_match[] = {
{.compatible = "qcom,coresight-modem-etm"},
{}
};
static struct platform_driver modem_etm_driver = {
.probe = modem_etm_probe,
.remove = modem_etm_remove,
.driver = {
.name = "coresight-modem-etm",
.owner = THIS_MODULE,
.of_match_table = modem_etm_match,
},
};
int __init modem_etm_init(void)
{
return platform_driver_register(&modem_etm_driver);
}
module_init(modem_etm_init);
void __exit modem_etm_exit(void)
{
platform_driver_unregister(&modem_etm_driver);
}
module_exit(modem_etm_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("CoreSight Modem ETM driver");

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -30,22 +30,6 @@
#define TIMEOUT_MS (5000)
enum coresight_svc_instance_id {
/* To force a 32 bit signed enum. Do not change or use */
CORESIGHT_SVC_INST_ID_ENUM_TYPE_MIN_ENUM_VAL_V01 = INT_MIN,
CORESIGHT_SVC_INST_ID_UNKNOWN_V01 = 0,
CORESIGHT_SVC_INST_ID_APPS_V01 = 1,
CORESIGHT_SVC_INST_ID_MODEM_V01 = 2,
CORESIGHT_SVC_INST_ID_WCN_V01 = 3,
CORESIGHT_SVC_INST_ID_RPM_V01 = 4,
CORESIGHT_SVC_INST_ID_AUDIO_V01 = 5,
CORESIGHT_SVC_INST_ID_VIDEO_V01 = 6,
CORESIGHT_SVC_INST_ID_GNSS_V01 = 7,
CORESIGHT_SVC_INST_ID_SENSOR_V01 = 8,
CORESIGHT_SVC_INST_ID_VPU_V01 = 10,
CORESIGHT_SVC_INST_ID_ENUM_TYPE_MAX_ENUM_VAL_V01 = INT_MAX,
};
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,

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -25,7 +25,7 @@
#include <linux/coresight.h>
#include "coresight-qmi.h"
#ifdef CONFIG_CORESIGHT_RPM_ETM_DEFAULT_ENABLE
#ifdef CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE
static int boot_enable = 1;
#else
static int boot_enable;
@ -34,7 +34,7 @@ module_param_named(
boot_enable, boot_enable, int, S_IRUGO
);
struct rpm_etm_drvdata {
struct remote_etm_drvdata {
struct device *dev;
struct coresight_device *csdev;
struct mutex mutex;
@ -47,9 +47,9 @@ struct rpm_etm_drvdata {
uint32_t inst_id;
};
static int rpm_etm_enable(struct coresight_device *csdev)
static int remote_etm_enable(struct coresight_device *csdev)
{
struct rpm_etm_drvdata *drvdata =
struct remote_etm_drvdata *drvdata =
dev_get_drvdata(csdev->dev.parent);
struct coresight_set_etm_req_msg_v01 req;
struct coresight_set_etm_resp_msg_v01 resp = { { 0, 0 } };
@ -103,16 +103,16 @@ static int rpm_etm_enable(struct coresight_device *csdev)
out:
mutex_unlock(&drvdata->mutex);
dev_info(drvdata->dev, "RPM ETM tracing enabled\n");
dev_info(drvdata->dev, "Remote ETM tracing enabled\n");
return 0;
err:
mutex_unlock(&drvdata->mutex);
return ret;
}
static void rpm_etm_disable(struct coresight_device *csdev)
static void remote_etm_disable(struct coresight_device *csdev)
{
struct rpm_etm_drvdata *drvdata =
struct remote_etm_drvdata *drvdata =
dev_get_drvdata(csdev->dev.parent);
struct coresight_set_etm_req_msg_v01 req;
struct coresight_set_etm_resp_msg_v01 resp = { { 0, 0 } };
@ -154,37 +154,37 @@ static void rpm_etm_disable(struct coresight_device *csdev)
out:
mutex_unlock(&drvdata->mutex);
dev_info(drvdata->dev, "RPM ETM tracing disabled\n");
dev_info(drvdata->dev, "Remote ETM tracing disabled\n");
return;
err:
mutex_unlock(&drvdata->mutex);
}
static const struct coresight_ops_source rpm_etm_source_ops = {
.enable = rpm_etm_enable,
.disable = rpm_etm_disable,
static const struct coresight_ops_source remote_etm_source_ops = {
.enable = remote_etm_enable,
.disable = remote_etm_disable,
};
static const struct coresight_ops rpm_cs_ops = {
.source_ops = &rpm_etm_source_ops,
static const struct coresight_ops remote_cs_ops = {
.source_ops = &remote_etm_source_ops,
};
static void rpm_etm_rcv_msg(struct work_struct *work)
static void remote_etm_rcv_msg(struct work_struct *work)
{
struct rpm_etm_drvdata *drvdata = container_of(work,
struct rpm_etm_drvdata,
work_rcv_msg);
struct remote_etm_drvdata *drvdata = container_of(work,
struct remote_etm_drvdata,
work_rcv_msg);
if (qmi_recv_msg(drvdata->handle) < 0)
dev_err(drvdata->dev, "%s: Error receiving QMI message\n",
__func__);
}
static void rpm_etm_notify(struct qmi_handle *handle,
static void remote_etm_notify(struct qmi_handle *handle,
enum qmi_event_type event, void *notify_priv)
{
struct rpm_etm_drvdata *drvdata =
(struct rpm_etm_drvdata *)notify_priv;
struct remote_etm_drvdata *drvdata =
(struct remote_etm_drvdata *)notify_priv;
switch (event) {
case QMI_RECV_MSG:
queue_work(drvdata->wq, &drvdata->work_rcv_msg);
@ -194,13 +194,13 @@ static void rpm_etm_notify(struct qmi_handle *handle,
}
}
static void rpm_etm_svc_arrive(struct work_struct *work)
static void remote_etm_svc_arrive(struct work_struct *work)
{
struct rpm_etm_drvdata *drvdata = container_of(work,
struct rpm_etm_drvdata,
work_svc_arrive);
struct remote_etm_drvdata *drvdata = container_of(work,
struct remote_etm_drvdata,
work_svc_arrive);
drvdata->handle = qmi_handle_create(rpm_etm_notify, drvdata);
drvdata->handle = qmi_handle_create(remote_etm_notify, drvdata);
if (!drvdata->handle) {
dev_err(drvdata->dev, "%s: QMI client handle alloc failed\n",
__func__);
@ -217,23 +217,23 @@ static void rpm_etm_svc_arrive(struct work_struct *work)
}
}
static void rpm_etm_svc_exit(struct work_struct *work)
static void remote_etm_svc_exit(struct work_struct *work)
{
struct rpm_etm_drvdata *drvdata = container_of(work,
struct rpm_etm_drvdata,
work_svc_exit);
struct remote_etm_drvdata *drvdata = container_of(work,
struct remote_etm_drvdata,
work_svc_exit);
qmi_handle_destroy(drvdata->handle);
drvdata->handle = NULL;
}
static int rpm_etm_svc_event_notify(struct notifier_block *this,
static int remote_etm_svc_event_notify(struct notifier_block *this,
unsigned long event,
void *data)
{
struct rpm_etm_drvdata *drvdata = container_of(this,
struct rpm_etm_drvdata,
nb);
struct remote_etm_drvdata *drvdata = container_of(this,
struct remote_etm_drvdata,
nb);
switch (event) {
case QMI_SERVER_ARRIVE:
@ -248,11 +248,11 @@ static int rpm_etm_svc_event_notify(struct notifier_block *this,
return 0;
}
static int rpm_etm_probe(struct platform_device *pdev)
static int remote_etm_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct coresight_platform_data *pdata;
struct rpm_etm_drvdata *drvdata;
struct remote_etm_drvdata *drvdata;
struct coresight_desc *desc;
int ret;
@ -273,24 +273,23 @@ static int rpm_etm_probe(struct platform_device *pdev)
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
if (!desc)
return -ENOMEM;
if (pdev->dev.of_node) {
ret = of_property_read_u32(pdev->dev.of_node, "qcom,inst-id",
&drvdata->inst_id);
if (ret)
drvdata->inst_id = CORESIGHT_SVC_INST_ID_RPM_V01;
return ret;
}
mutex_init(&drvdata->mutex);
drvdata->nb.notifier_call = rpm_etm_svc_event_notify;
drvdata->nb.notifier_call = remote_etm_svc_event_notify;
drvdata->wq = create_singlethread_workqueue("rpm-etm");
drvdata->wq = create_singlethread_workqueue(dev_name(dev));
if (!drvdata->wq)
return -EFAULT;
INIT_WORK(&drvdata->work_svc_arrive, rpm_etm_svc_arrive);
INIT_WORK(&drvdata->work_svc_exit, rpm_etm_svc_exit);
INIT_WORK(&drvdata->work_rcv_msg, rpm_etm_rcv_msg);
INIT_WORK(&drvdata->work_svc_arrive, remote_etm_svc_arrive);
INIT_WORK(&drvdata->work_svc_exit, remote_etm_svc_exit);
INIT_WORK(&drvdata->work_rcv_msg, remote_etm_rcv_msg);
ret = qmi_svc_event_notifier_register(CORESIGHT_QMI_SVC_ID,
CORESIGHT_QMI_VERSION,
drvdata->inst_id,
@ -300,7 +299,7 @@ static int rpm_etm_probe(struct platform_device *pdev)
desc->type = CORESIGHT_DEV_TYPE_SOURCE;
desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
desc->ops = &rpm_cs_ops;
desc->ops = &remote_cs_ops;
desc->pdata = pdev->dev.platform_data;
desc->dev = &pdev->dev;
desc->owner = THIS_MODULE;
@ -309,7 +308,7 @@ static int rpm_etm_probe(struct platform_device *pdev)
ret = PTR_ERR(drvdata->csdev);
goto err1;
}
dev_info(dev, "RPM ETM initialized\n");
dev_info(dev, "Remote ETM initialized\n");
if (boot_enable)
coresight_enable(drvdata->csdev);
@ -325,40 +324,40 @@ err0:
return ret;
}
static int rpm_etm_remove(struct platform_device *pdev)
static int remote_etm_remove(struct platform_device *pdev)
{
struct rpm_etm_drvdata *drvdata = platform_get_drvdata(pdev);
struct remote_etm_drvdata *drvdata = platform_get_drvdata(pdev);
coresight_unregister(drvdata->csdev);
return 0;
}
static struct of_device_id rpm_etm_match[] = {
{.compatible = "qcom,coresight-rpm-etm"},
static struct of_device_id remote_etm_match[] = {
{.compatible = "qcom,coresight-remote-etm"},
{}
};
static struct platform_driver rpm_etm_driver = {
.probe = rpm_etm_probe,
.remove = rpm_etm_remove,
static struct platform_driver remote_etm_driver = {
.probe = remote_etm_probe,
.remove = remote_etm_remove,
.driver = {
.name = "coresight-rpm-etm",
.name = "coresight-remote-etm",
.owner = THIS_MODULE,
.of_match_table = rpm_etm_match,
.of_match_table = remote_etm_match,
},
};
int __init rpm_etm_init(void)
int __init remote_etm_init(void)
{
return platform_driver_register(&rpm_etm_driver);
return platform_driver_register(&remote_etm_driver);
}
module_init(rpm_etm_init);
module_init(remote_etm_init);
void __exit rpm_etm_exit(void)
void __exit remote_etm_exit(void)
{
platform_driver_unregister(&rpm_etm_driver);
platform_driver_unregister(&remote_etm_driver);
}
module_exit(rpm_etm_exit);
module_exit(remote_etm_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("CoreSight RPM ETM driver");
MODULE_DESCRIPTION("CoreSight Remote ETM driver");

View File

@ -1,354 +0,0 @@
/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/sysfs.h>
#include <linux/mutex.h>
#include <linux/of_coresight.h>
#include <linux/coresight.h>
#include "coresight-qmi.h"
#ifdef CONFIG_CORESIGHT_WCN_ETM_DEFAULT_ENABLE
static int boot_enable = 1;
#else
static int boot_enable;
#endif
module_param_named(
boot_enable, boot_enable, int, S_IRUGO
);
struct wcn_etm_drvdata {
struct device *dev;
struct coresight_device *csdev;
struct mutex mutex;
struct workqueue_struct *wq;
struct qmi_handle *handle;
struct work_struct work_svc_arrive;
struct work_struct work_svc_exit;
struct work_struct work_rcv_msg;
struct notifier_block nb;
};
static int wcn_etm_enable(struct coresight_device *csdev)
{
struct wcn_etm_drvdata *drvdata =
dev_get_drvdata(csdev->dev.parent);
struct coresight_set_etm_req_msg_v01 req;
struct coresight_set_etm_resp_msg_v01 resp = { { 0, 0 } };
struct msg_desc req_desc, resp_desc;
int ret;
mutex_lock(&drvdata->mutex);
/*
* The QMI handle may be NULL in the following scenarios:
* 1. QMI service is not present
* 2. QMI service is present but attempt to enable remote ETM is earlier
* than service is ready to handle request
* 3. Connection between QMI client and QMI service failed
*
* Enable CoreSight without processing further QMI commands which
* provides the option to enable remote ETM by other means.
*/
if (!drvdata->handle) {
dev_info(drvdata->dev,
"%s: QMI service unavailable. Skipping QMI requests\n",
__func__);
goto out;
}
req.state = CORESIGHT_ETM_STATE_ENABLED_V01;
req_desc.msg_id = CORESIGHT_QMI_SET_ETM_REQ_V01;
req_desc.max_msg_len = CORESIGHT_QMI_SET_ETM_REQ_MAX_LEN;
req_desc.ei_array = coresight_set_etm_req_msg_v01_ei;
resp_desc.msg_id = CORESIGHT_QMI_SET_ETM_RESP_V01;
resp_desc.max_msg_len = CORESIGHT_QMI_SET_ETM_RESP_MAX_LEN;
resp_desc.ei_array = coresight_set_etm_resp_msg_v01_ei;
ret = qmi_send_req_wait(drvdata->handle, &req_desc, &req, sizeof(req),
&resp_desc, &resp, sizeof(resp), TIMEOUT_MS);
if (ret < 0) {
dev_err(drvdata->dev, "%s: QMI send req failed %d\n", __func__,
ret);
goto err;
}
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
dev_err(drvdata->dev, "%s: QMI request failed %d %d\n",
__func__, resp.resp.result, resp.resp.error);
ret = -EREMOTEIO;
goto err;
}
out:
mutex_unlock(&drvdata->mutex);
dev_info(drvdata->dev, "Wireless ETM tracing enabled\n");
return 0;
err:
mutex_unlock(&drvdata->mutex);
return ret;
}
static void wcn_etm_disable(struct coresight_device *csdev)
{
struct wcn_etm_drvdata *drvdata =
dev_get_drvdata(csdev->dev.parent);
struct coresight_set_etm_req_msg_v01 req;
struct coresight_set_etm_resp_msg_v01 resp = { { 0, 0 } };
struct msg_desc req_desc, resp_desc;
int ret;
mutex_lock(&drvdata->mutex);
if (!drvdata->handle) {
dev_info(drvdata->dev,
"%s: QMI service unavailable. Skipping QMI requests\n",
__func__);
goto out;
}
req.state = CORESIGHT_ETM_STATE_DISABLED_V01;
req_desc.msg_id = CORESIGHT_QMI_SET_ETM_REQ_V01;
req_desc.max_msg_len = CORESIGHT_QMI_SET_ETM_REQ_MAX_LEN;
req_desc.ei_array = coresight_set_etm_req_msg_v01_ei;
resp_desc.msg_id = CORESIGHT_QMI_SET_ETM_RESP_V01;
resp_desc.max_msg_len = CORESIGHT_QMI_SET_ETM_RESP_MAX_LEN;
resp_desc.ei_array = coresight_set_etm_resp_msg_v01_ei;
ret = qmi_send_req_wait(drvdata->handle, &req_desc, &req, sizeof(req),
&resp_desc, &resp, sizeof(resp), TIMEOUT_MS);
if (ret < 0) {
dev_err(drvdata->dev, "%s: QMI send req failed %d\n", __func__,
ret);
goto err;
}
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
dev_err(drvdata->dev, "%s: QMI request failed %d %d\n",
__func__, resp.resp.result, resp.resp.error);
goto err;
}
out:
mutex_unlock(&drvdata->mutex);
dev_info(drvdata->dev, "Wireless ETM tracing disabled\n");
return;
err:
mutex_unlock(&drvdata->mutex);
}
static const struct coresight_ops_source wcn_etm_source_ops = {
.enable = wcn_etm_enable,
.disable = wcn_etm_disable,
};
static const struct coresight_ops wcn_cs_ops = {
.source_ops = &wcn_etm_source_ops,
};
static void wcn_etm_rcv_msg(struct work_struct *work)
{
struct wcn_etm_drvdata *drvdata = container_of(work,
struct wcn_etm_drvdata,
work_rcv_msg);
if (qmi_recv_msg(drvdata->handle) < 0)
dev_err(drvdata->dev, "%s: Error receiving QMI message\n",
__func__);
}
static void wcn_etm_notify(struct qmi_handle *handle,
enum qmi_event_type event, void *notify_priv)
{
struct wcn_etm_drvdata *drvdata =
(struct wcn_etm_drvdata *)notify_priv;
switch (event) {
case QMI_RECV_MSG:
queue_work(drvdata->wq, &drvdata->work_rcv_msg);
break;
default:
break;
}
}
static void wcn_etm_svc_arrive(struct work_struct *work)
{
struct wcn_etm_drvdata *drvdata = container_of(work,
struct wcn_etm_drvdata,
work_svc_arrive);
drvdata->handle = qmi_handle_create(wcn_etm_notify, drvdata);
if (!drvdata->handle) {
dev_err(drvdata->dev, "%s: QMI client handle alloc failed\n",
__func__);
return;
}
if (qmi_connect_to_service(drvdata->handle, CORESIGHT_QMI_SVC_ID,
CORESIGHT_QMI_VERSION,
CORESIGHT_SVC_INST_ID_WCN_V01) < 0) {
dev_err(drvdata->dev,
"%s: Could not connect handle to service\n", __func__);
qmi_handle_destroy(drvdata->handle);
drvdata->handle = NULL;
}
}
static void wcn_etm_svc_exit(struct work_struct *work)
{
struct wcn_etm_drvdata *drvdata = container_of(work,
struct wcn_etm_drvdata,
work_svc_exit);
qmi_handle_destroy(drvdata->handle);
drvdata->handle = NULL;
}
static int wcn_etm_svc_event_notify(struct notifier_block *this,
unsigned long event,
void *data)
{
struct wcn_etm_drvdata *drvdata = container_of(this,
struct wcn_etm_drvdata,
nb);
switch (event) {
case QMI_SERVER_ARRIVE:
queue_work(drvdata->wq, &drvdata->work_svc_arrive);
break;
case QMI_SERVER_EXIT:
queue_work(drvdata->wq, &drvdata->work_svc_exit);
break;
default:
break;
}
return 0;
}
static int wcn_etm_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct coresight_platform_data *pdata;
struct wcn_etm_drvdata *drvdata;
struct coresight_desc *desc;
int ret;
if (pdev->dev.of_node) {
pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
pdev->dev.platform_data = pdata;
}
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
drvdata->dev = &pdev->dev;
platform_set_drvdata(pdev, drvdata);
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
if (!desc)
return -ENOMEM;
mutex_init(&drvdata->mutex);
drvdata->nb.notifier_call = wcn_etm_svc_event_notify;
drvdata->wq = create_singlethread_workqueue("wcn-etm");
if (!drvdata->wq)
return -EFAULT;
INIT_WORK(&drvdata->work_svc_arrive, wcn_etm_svc_arrive);
INIT_WORK(&drvdata->work_svc_exit, wcn_etm_svc_exit);
INIT_WORK(&drvdata->work_rcv_msg, wcn_etm_rcv_msg);
ret = qmi_svc_event_notifier_register(CORESIGHT_QMI_SVC_ID,
CORESIGHT_QMI_VERSION,
CORESIGHT_SVC_INST_ID_WCN_V01,
&drvdata->nb);
if (ret < 0)
goto err0;
desc->type = CORESIGHT_DEV_TYPE_SOURCE;
desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
desc->ops = &wcn_cs_ops;
desc->pdata = pdev->dev.platform_data;
desc->dev = &pdev->dev;
desc->owner = THIS_MODULE;
drvdata->csdev = coresight_register(desc);
if (IS_ERR(drvdata->csdev)) {
ret = PTR_ERR(drvdata->csdev);
goto err1;
}
dev_info(dev, "Wireless ETM initialized\n");
if (boot_enable)
coresight_enable(drvdata->csdev);
return 0;
err1:
qmi_svc_event_notifier_unregister(CORESIGHT_QMI_SVC_ID,
CORESIGHT_QMI_VERSION,
CORESIGHT_SVC_INST_ID_WCN_V01,
&drvdata->nb);
err0:
destroy_workqueue(drvdata->wq);
return ret;
}
static int wcn_etm_remove(struct platform_device *pdev)
{
struct wcn_etm_drvdata *drvdata = platform_get_drvdata(pdev);
coresight_unregister(drvdata->csdev);
return 0;
}
static struct of_device_id wcn_etm_match[] = {
{.compatible = "qcom,coresight-wcn-etm"},
{}
};
static struct platform_driver wcn_etm_driver = {
.probe = wcn_etm_probe,
.remove = wcn_etm_remove,
.driver = {
.name = "coresight-wcn-etm",
.owner = THIS_MODULE,
.of_match_table = wcn_etm_match,
},
};
int __init wcn_etm_init(void)
{
return platform_driver_register(&wcn_etm_driver);
}
module_init(wcn_etm_init);
void __exit wcn_etm_exit(void)
{
platform_driver_unregister(&wcn_etm_driver);
}
module_exit(wcn_etm_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("CoreSight Wireless ETM driver");