cts-verifier device suspend test fail —— qrtr改为非唤醒模式
device suspend test
设备休眠测试
install CtsVerifier.apk
手动执行device suspend test项:
按要求设置相应环境后开始测试,测试时需要灭屏,待几分钟后会有测试结束提示音
结果
testAccelBatchingInAPSuspendZeroReportLatency 该项测试失败
显示:
[TestExecution] Device did not go into suspend during test execution
分析
ap侧无法进入suspend mode
从log中可以看到如下内容:
Abort: Last active Wakeup Source: qrtr_ws PM: suspend exit
在测试过程中,灭屏后ap侧被唤醒源qrtr_ws
持续唤醒,即qrtr通信(ap与modem之间通信)唤醒kernel,导致无法进入suspend mode
修改
据了解,该问题为高通老平台共性问题,需要修改qrtr通信改为非唤醒模式
原理:增加对从子系统接收数据时过滤的服务支持,如果service id在白名单中,它将不会持有唤醒源。
修改参考(kernel-5.4,system t,chip t):
kernel/msm-5.4/net/qrtr/haven.c
static int qrtr_haven_probe(struct platform_device *pdev)
{
...
qdev->ep.xmit = qrtr_haven_send;
- ret = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NET_ID_AUTO, false);
+ ret = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NET_ID_AUTO, false, NULL);
if (ret)
goto register_fail;
...
kernel/msm-5.4/net/qrtr/mhi.c
static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev,
const struct mhi_device_id *id)
{
...
dev_set_drvdata(&mhi_dev->dev, qdev);
- rc = qrtr_endpoint_register(&qdev->ep, net_id, rt);
+ rc = qrtr_endpoint_register(&qdev->ep, net_id, rt, NULL);
if (rc)
return rc;
...
kernel/msm-5.4/net/qrtr/ns.c
unsigned int qrtr_get_service_id(unsigned int node_id, unsigned int port_id)
{
struct qrtr_server *srv;
struct qrtr_node *node;
unsigned long index;
- node = node_get(node_id);
+ node = xa_load(&nodes, node_id);
if (!node)
return 0;
...
kernel/msm-5.4/net/qrtr/qrtr.h
+ #define MAX_NON_WAKE_SVC_LEN 5
int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int net_id,
- bool rt);
+ bool rt, u32 *svc_arr);
...
kernel/msm-5.4/net/qrtr/qrtr.c
struct qrtr_node {
...
struct wakeup_source *ws;
void *ilc;
+ u32 nonwake_svc[MAX_NON_WAKE_SVC_LEN];
};
...
int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
...
unsigned int ver;
size_t hdrlen;
- int errcode;
+ int errcode,i;
+ bool wake = true;
+ int svc_id;
...
/* Force wakeup for all packets except for sensors */
- if (node->nid != 9)
+ if (node->nid != 9 && node->nid != 5)
pm_wakeup_ws_event(node->ws, qrtr_wakeup_ms, true);
+ if (node->nid == 5) {
+ svc_id = qrtr_get_service_id(cb->src_node, cb->src_port);
+ if (svc_id > 0) {
+ for (i = 0; i < MAX_NON_WAKE_SVC_LEN; i++) {
+ if (svc_id == node->nonwake_svc[i]) {
+ wake = false;
+ break;
+ }
+ }
+ }
+ if (wake)
+ pm_wakeup_ws_event(node->ws, qrtr_wakeup_ms, true);
+ }
qrtr_port_put(ipc);
}
...
}
...
int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int net_id,
- bool rt)
+ bool rt, u32 *svc_arr)
{
...
if (rt)
sched_setscheduler(node->task, SCHED_FIFO, ¶m);
+ if (svc_arr)
+ memcpy(node->nonwake_svc, svc_arr, MAX_NON_WAKE_SVC_LEN * sizeof(int));
mutex_init(&node->qrtr_tx_lock);
...
kernel/msm-5.4/net/qrtr/smd.c
static int qcom_smd_qrtr_probe(struct rpmsg_device *rpdev)
{
struct qrtr_smd_dev *qdev;
u32 net_id;
bool rt;
- int rc;
+ int rc,size;
u32 *svc_arr = NULL;
pr_info("%s:Entered\n", __func__);
...
rt = of_property_read_bool(rpdev->dev.of_node, "qcom,low-latency");
- rc = qrtr_endpoint_register(&qdev->ep, net_id, rt);
+ size = of_property_count_u32_elems(rpdev->dev.of_node, "qcom,non-wake-svc");
+ if (size > 0) {
+ if (size > MAX_NON_WAKE_SVC_LEN)
+ size = MAX_NON_WAKE_SVC_LEN;
+ svc_arr = kmalloc_array(size, sizeof(u32), GFP_KERNEL);
+
+ of_property_read_u32_array(rpdev->dev.of_node, "qcom,non-wake-svc",
+ svc_arr, size);
+ }
+ rc = qrtr_endpoint_register(&qdev->ep, net_id, rt, svc_arr);
+ kfree(svc_arr);
+
if (rc)
return rc;
...
platform/vendor/qcom-proprietary/devicetree/qcom/xxx.dtsi
qcom,adsp_qrtr {
qcom,glink-channels = "IPCRTR";
qcom,intents = <0x800 5
0x2000 3
0x4400 2>;
+ qcom,non-wake-svc = <0x190>;
};
如果该仓有多个产品共用,且有些产品需要qrtr唤醒,而一些产品需要qrtr在非唤醒模式,那么可以加config进行区分:
kernel/msm-5.4/net/qrtr/Kconfig 添加
+config QRTR_GKI
+ bool "QRTR GKI"
+ default n
+ help
+ To solve the abi check fail, this macro is added.
在需要添加qrtr非唤醒的的产品上添加:
kernel/msm-5.4/arch/arm64/configs/vendor/xxx.config
+CONFIG_QRTR_GKI=y
在前边修改的地方添加宏控以区分:
+#ifdef CONFIG_QRTR_GKI
...
+#else
...
+#endif