mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 11:37:06 +02:00
net: qrtr: Move tx_resume handling to work context
There will be non-atomic work associated with receiving the tx resume packet from the remote. Move the handling to work function context in preparation for the non-blocking socket blocking improvement. In system heavy load cases the rx work queued in global worker queue is getting delayed and causing clients request timeouts. Create and use separate worker thread to process qrtr rx packets. Change-Id: I2389bdcffba068258650bfbb579f8cb98a0ac928 Signed-off-by: Chris Lew <quic_clew@quicinc.com>
This commit is contained in:
parent
ed4fba13e9
commit
c742a81975
|
|
@ -4,6 +4,7 @@
|
|||
* Copyright (c) 2013, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/qrtr.h>
|
||||
|
|
@ -136,6 +137,9 @@ static DEFINE_SPINLOCK(qrtr_port_lock);
|
|||
* @hello_sent: hello packet sent to endpoint
|
||||
* @rx_queue: receive queue
|
||||
* @item: list item for broadcast list
|
||||
* @kworker: worker thread for recv work
|
||||
* @task: task to run the worker thread
|
||||
* @read_data: scheduled work for recv work
|
||||
*/
|
||||
struct qrtr_node {
|
||||
struct mutex ep_lock;
|
||||
|
|
@ -149,6 +153,10 @@ struct qrtr_node {
|
|||
|
||||
struct sk_buff_head rx_queue;
|
||||
struct list_head item;
|
||||
|
||||
struct kthread_worker kworker;
|
||||
struct task_struct *task;
|
||||
struct kthread_work read_data;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -227,6 +235,8 @@ static void __qrtr_node_release(struct kref *kref)
|
|||
list_del(&node->item);
|
||||
up_write(&qrtr_epts_lock);
|
||||
|
||||
kthread_flush_worker(&node->kworker);
|
||||
kthread_stop(node->task);
|
||||
skb_queue_purge(&node->rx_queue);
|
||||
|
||||
/* Free tx flow counters */
|
||||
|
|
@ -235,6 +245,7 @@ static void __qrtr_node_release(struct kref *kref)
|
|||
radix_tree_iter_delete(&node->qrtr_tx_flow, &iter, slot);
|
||||
kfree(flow);
|
||||
}
|
||||
|
||||
kfree(node);
|
||||
}
|
||||
|
||||
|
|
@ -620,7 +631,8 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
|
|||
}
|
||||
|
||||
if (cb->type == QRTR_TYPE_RESUME_TX) {
|
||||
qrtr_tx_resume(node, skb);
|
||||
skb_queue_tail(&node->rx_queue, skb);
|
||||
kthread_queue_work(&node->kworker, &node->read_data);
|
||||
} else {
|
||||
ipc = qrtr_port_lookup(cb->dst_port);
|
||||
if (!ipc) {
|
||||
|
|
@ -671,6 +683,21 @@ static struct sk_buff *qrtr_alloc_ctrl_packet(struct qrtr_ctrl_pkt **pkt,
|
|||
return skb;
|
||||
}
|
||||
|
||||
/* Handle not atomic operations for a received packet. */
|
||||
static void qrtr_node_rx_work(struct kthread_work *work)
|
||||
{
|
||||
struct qrtr_node *node = container_of(work, struct qrtr_node,
|
||||
read_data);
|
||||
struct sk_buff *skb;
|
||||
|
||||
while ((skb = skb_dequeue(&node->rx_queue)) != NULL) {
|
||||
struct qrtr_cb *cb = (struct qrtr_cb *)skb->cb;
|
||||
|
||||
if (cb->type == QRTR_TYPE_RESUME_TX)
|
||||
qrtr_tx_resume(node, skb);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* qrtr_endpoint_register() - register a new endpoint
|
||||
* @ep: endpoint to register
|
||||
|
|
@ -697,6 +724,14 @@ int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int nid)
|
|||
node->ep = ep;
|
||||
atomic_set(&node->hello_sent, 0);
|
||||
|
||||
kthread_init_work(&node->read_data, qrtr_node_rx_work);
|
||||
kthread_init_worker(&node->kworker);
|
||||
node->task = kthread_run(kthread_worker_fn, &node->kworker, "qrtr_rx");
|
||||
if (IS_ERR(node->task)) {
|
||||
kfree(node);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
INIT_RADIX_TREE(&node->qrtr_tx_flow, GFP_KERNEL);
|
||||
mutex_init(&node->qrtr_tx_lock);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user