net: qrtr: Add pm_wakeup_event() support

In some cases system enters into suspend state before handling
incoming packets and cause delay in communication.

Add pm_wakup_event() to abort the suspend when a packet is received.

Force a wakeup when queueing packets to a socket. This is needed to
give userspace clients a chance to run if the device is going into
system suspend. The wakeup event should force the device to abort
suspend.

The only node that should not behave this way is the SLPI node because
sensor stream race conditions cause suspend issues and power drain
issues.

There was an update to add a device parameter into
wakeup_source_register().

Change-Id: Ie69be3a46309f6a05cfbff0642b95194c2d6e955
Signed-off-by: Chris Lew <quic_clew@quicinc.com>
This commit is contained in:
Chris Lew 2022-10-27 11:07:47 -07:00
parent a34e1c5cea
commit 533788bfca

View File

@ -13,6 +13,7 @@
#include <linux/wait.h>
#include <linux/rwsem.h>
#include <linux/uidgid.h>
#include <linux/pm_wakeup.h>
#include <net/sock.h>
#include <uapi/linux/sched/types.h>
@ -153,6 +154,7 @@ static struct work_struct qrtr_backup_work;
* @task: task to run the worker thread
* @read_data: scheduled work for recv work
* @say_hello: scheduled work for initiating hello
* @ws: wakeupsource avoid system suspend
*/
struct qrtr_node {
struct mutex ep_lock;
@ -173,6 +175,8 @@ struct qrtr_node {
struct task_struct *task;
struct kthread_work read_data;
struct kthread_work say_hello;
struct wakeup_source *ws;
};
/**
@ -254,6 +258,7 @@ static void __qrtr_node_release(struct kref *kref)
kthread_flush_worker(&node->kworker);
kthread_stop(node->task);
skb_queue_purge(&node->rx_queue);
wakeup_source_unregister(node->ws);
/* Free tx flow counters */
radix_tree_for_each_slot(slot, &node->qrtr_tx_flow, &iter, 0) {
@ -727,6 +732,7 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
if (cb->type != QRTR_TYPE_DATA || cb->dst_node != qrtr_local_nid) {
skb_queue_tail(&node->rx_queue, skb);
kthread_queue_work(&node->kworker, &node->read_data);
__pm_wakeup_event(node->ws, 0);
} else {
ipc = qrtr_port_lookup(cb->dst_port);
if (!ipc) {
@ -739,6 +745,10 @@ 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)
__pm_wakeup_event(node->ws, 0);
qrtr_port_put(ipc);
}
@ -985,6 +995,8 @@ int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int net_id,
up_write(&qrtr_epts_lock);
ep->node = node;
node->ws = wakeup_source_register(NULL, "qrtr_ws");
kthread_queue_work(&node->kworker, &node->say_hello);
return 0;
}