From e13155f7efeca3d11db336155716e3cf2d4576e8 Mon Sep 17 00:00:00 2001 From: Arun Prakash Date: Fri, 23 Oct 2020 16:19:54 +0530 Subject: [PATCH] net: qrtr: Cleanup flow control during DEL proc Flow control cleanup of remote socket is not happening in case of DEL proc which will cause flow control hit for that remote socket once the proc is active again. Cleanup flow control on the reception of DEL proc command. Change-Id: I9cbaa121d7ca39a887b423ee274652dccaba8a38 Signed-off-by: Arun Prakash --- net/qrtr/qrtr.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index 9d7e8af02471..f0d1bd7e09f4 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -211,7 +211,7 @@ static int qrtr_local_enqueue(struct qrtr_node *node, struct sk_buff *skb, static int qrtr_bcast_enqueue(struct qrtr_node *node, struct sk_buff *skb, int type, struct sockaddr_qrtr *from, struct sockaddr_qrtr *to, unsigned int flags); -static void qrtr_handle_del_proc(struct sk_buff *skb); +static void qrtr_handle_del_proc(struct qrtr_node *node, struct sk_buff *skb); static void qrtr_cleanup_flow_control(struct qrtr_node *node, struct sk_buff *skb); @@ -300,6 +300,10 @@ static void qrtr_log_rx_msg(struct qrtr_node *node, struct sk_buff *skb) QRTR_INFO(node->ilc, "RX CTRL: cmd:0x%x node[0x%x]\n", cb->type, cb->src_node); + else if (cb->type == QRTR_TYPE_DEL_PROC) + QRTR_INFO(node->ilc, + "RX CTRL: cmd:0x%x node[0x%x]\n", + cb->type, le32_to_cpu(pkt.proc.node)); } } @@ -1043,7 +1047,7 @@ static void qrtr_node_rx_work(struct kthread_work *work) cb->type == QRTR_TYPE_DATA) { qrtr_fwd_pkt(skb, cb); } else if (cb->type == QRTR_TYPE_DEL_PROC) { - qrtr_handle_del_proc(skb); + qrtr_handle_del_proc(node, skb); } else { ipc = qrtr_port_lookup(cb->dst_port); if (!ipc) { @@ -1101,14 +1105,37 @@ static void qrtr_cleanup_flow_control(struct qrtr_node *node, mutex_unlock(&node->qrtr_tx_lock); } -static void qrtr_handle_del_proc(struct sk_buff *skb) +static void qrtr_handle_del_proc(struct qrtr_node *node, struct sk_buff *skb) { struct sockaddr_qrtr src = {AF_QIPCRTR, 0, QRTR_PORT_CTRL}; struct sockaddr_qrtr dst = {AF_QIPCRTR, qrtr_local_nid, QRTR_PORT_CTRL}; struct qrtr_ctrl_pkt pkt = {0,}; + struct qrtr_tx_flow_waiter *waiter; + struct qrtr_tx_flow_waiter *temp; + struct radix_tree_iter iter; + struct qrtr_tx_flow *flow; + void __rcu **slot; + unsigned long node_id; skb_copy_bits(skb, 0, &pkt, sizeof(pkt)); src.sq_node = le32_to_cpu(pkt.proc.node); + /* Free tx flow counters */ + mutex_lock(&node->qrtr_tx_lock); + radix_tree_for_each_slot(slot, &node->qrtr_tx_flow, &iter, 0) { + flow = rcu_dereference(*slot); + /* extract node id from the index key */ + node_id = (iter.index & 0xFFFFFFFF00000000) >> 32; + if (node_id != src.sq_node) + continue; + list_for_each_entry_safe(waiter, temp, &flow->waiters, node) { + list_del(&waiter->node); + sock_put(waiter->sk); + kfree(waiter); + } + kfree(flow); + radix_tree_delete(&node->qrtr_tx_flow, iter.index); + } + mutex_unlock(&node->qrtr_tx_lock); memset(&pkt, 0, sizeof(pkt)); pkt.cmd = cpu_to_le32(QRTR_TYPE_BYE);