net: qrtr: Support pm_wakeup_event() based on svc

Instead of filtering pm_wakeup_event() call via node ID, add support to
do it based on the service ID. This provides more fine control over
which incoming packet can wakeup APPS.

Change-Id: I1e4a7f6d04a2e37104191bedc5d87070aabc002b
Signed-off-by: Tony Truong <quic_truong@quicinc.com>
This commit is contained in:
Tony Truong 2022-01-26 23:24:05 -08:00 committed by Gerrit - the friendly Code Review server
parent fe94f61475
commit 1da9ab5d38
5 changed files with 53 additions and 8 deletions

View File

@ -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, &param);
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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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;