diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c index e1d6c1813173..7bfad4db18ad 100644 --- a/net/qrtr/af_qrtr.c +++ b/net/qrtr/af_qrtr.c @@ -185,6 +185,8 @@ struct qrtr_node { struct wakeup_source *ws; void *ilc; + + struct xarray no_wake_svc; /* services that will not wake up APPS */ }; /** @@ -799,6 +801,7 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) unsigned int ver; size_t hdrlen; int errcode; + int svc_id; if (len == 0 || len & 3) return -EINVAL; @@ -906,8 +909,9 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) goto err; } - /* Force wakeup for all packets except for sensors */ - if (node->nid != 9) + /* Force wakeup based on services */ + svc_id = qrtr_get_service_id(cb->src_node, cb->src_port); + if (!xa_load(&node->no_wake_svc, svc_id)) pm_wakeup_ws_event(node->ws, qrtr_wakeup_ms, true); qrtr_port_put(ipc); @@ -1115,13 +1119,16 @@ static void qrtr_hello_work(struct kthread_work *work) * @ep: endpoint to register * @nid: desired node id; may be QRTR_EP_NID_AUTO for auto-assignment * @rt: flag to notify real time low latency endpoint + * @no_wake: array of services to not wake up * Return: 0 on success; negative error code on failure * * The specified endpoint must have the xmit function pointer set on call. */ int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int net_id, - bool rt) + bool rt, struct qrtr_array *no_wake) { + int rc, i; + size_t size; struct qrtr_node *node; struct sched_param param = {.sched_priority = 1}; @@ -1151,6 +1158,17 @@ int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int net_id, if (rt) sched_setscheduler(node->task, SCHED_FIFO, ¶m); + xa_init(&node->no_wake_svc); + size = no_wake ? no_wake->size : 0; + for (i = 0; i < size; i++) { + rc = xa_insert(&node->no_wake_svc, no_wake->arr[i], node, + GFP_KERNEL); + if (rc) { + kfree(node); + return rc; + } + } + INIT_RADIX_TREE(&node->qrtr_tx_flow, GFP_KERNEL); mutex_init(&node->qrtr_tx_lock); diff --git a/net/qrtr/gunyah.c b/net/qrtr/gunyah.c index 38297f8d375b..f96d9dcc163d 100644 --- a/net/qrtr/gunyah.c +++ b/net/qrtr/gunyah.c @@ -454,7 +454,8 @@ static int qrtr_gunyah_rm_cb(struct notifier_block *nb, unsigned long cmd, if (vm_status_payload->vm_status == GH_RM_VM_STATUS_READY) { qrtr_gunyah_fifo_init(qdev); - if (qrtr_endpoint_register(&qdev->ep, QRTR_EP_NET_ID_AUTO, false)) { + if (qrtr_endpoint_register(&qdev->ep, QRTR_EP_NET_ID_AUTO, + false, NULL)) { pr_err("%s: endpoint register failed\n", __func__); return NOTIFY_DONE; } @@ -649,7 +650,7 @@ static int qrtr_gunyah_probe(struct platform_device *pdev) qdev->ep.xmit = qrtr_gunyah_send; if (!qdev->master) { ret = qrtr_endpoint_register(&qdev->ep, QRTR_EP_NET_ID_AUTO, - false); + false, NULL); if (ret) goto register_fail; } diff --git a/net/qrtr/mhi.c b/net/qrtr/mhi.c index d21a53449559..30e8c8203d47 100644 --- a/net/qrtr/mhi.c +++ b/net/qrtr/mhi.c @@ -130,7 +130,7 @@ static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev, qrtr_mhi_of_parse(mhi_dev, &net_id, &rt); - rc = qrtr_endpoint_register(&qdev->ep, net_id, rt); + rc = qrtr_endpoint_register(&qdev->ep, net_id, rt, NULL); if (rc) return rc; diff --git a/net/qrtr/qrtr.h b/net/qrtr/qrtr.h index f0ee970a8546..95d9d720e0ef 100644 --- a/net/qrtr/qrtr.h +++ b/net/qrtr/qrtr.h @@ -26,8 +26,20 @@ struct qrtr_endpoint { struct qrtr_node *node; }; +/** + * struct qrtr_array - array with size + * @arr: elements in the array + * @size: number of elements + * + * An array with its size provided. + */ +struct qrtr_array { + u32 *arr; + size_t size; +}; + int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int net_id, - bool rt); + bool rt, struct qrtr_array *no_wake); void qrtr_endpoint_unregister(struct qrtr_endpoint *ep); diff --git a/net/qrtr/smd.c b/net/qrtr/smd.c index cc2381c08f26..228b4407a7b1 100644 --- a/net/qrtr/smd.c +++ b/net/qrtr/smd.c @@ -66,7 +66,9 @@ static int qcom_smd_qrtr_send(struct qrtr_endpoint *ep, struct sk_buff *skb) static int qcom_smd_qrtr_probe(struct rpmsg_device *rpdev) { + struct qrtr_array svc_arr = {NULL, 0}; struct qrtr_smd_dev *qdev; + size_t size; u32 net_id; bool rt; int rc; @@ -85,7 +87,19 @@ static int qcom_smd_qrtr_probe(struct rpmsg_device *rpdev) 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,no-wake-svc"); + if (size > 0) { + svc_arr.size = size; + svc_arr.arr = kmalloc_array(size, sizeof(u32), GFP_KERNEL); + if (!svc_arr.arr) + return -ENOMEM; + + of_property_read_u32_array(rpdev->dev.of_node, "qcom,no-wake-svc", + svc_arr.arr, size); + } + + rc = qrtr_endpoint_register(&qdev->ep, net_id, rt, &svc_arr); + kfree(svc_arr.arr); if (rc) { dev_err(qdev->dev, "endpoint register failed: %d, low-latency: %d\n", rc, rt); return rc;