Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7006b6e2 authored by Arun Prakash's avatar Arun Prakash Committed by Sivaji Boddupilli
Browse files

net: qrtr: Cleanup flow control during remote socket release



In case of Q6 SSR for MSM+MDM target flow control cleanup is
not happening for the remote socket on MSM which might cause
flow control hit for that remote socket.

Cleanup flow control for each deleted remote server or client.

Change-Id: Ieaff0d6bb2605e9db54f93dd199dd481420067af
Signed-off-by: default avatarArun Prakash <app@codeaurora.org>
parent 48e493cb
Loading
Loading
Loading
Loading
+47 −0
Original line number Original line Diff line number Diff line
@@ -212,6 +212,8 @@ static int qrtr_bcast_enqueue(struct qrtr_node *node, struct sk_buff *skb,
			      int type, struct sockaddr_qrtr *from,
			      int type, struct sockaddr_qrtr *from,
			      struct sockaddr_qrtr *to, unsigned int flags);
			      struct sockaddr_qrtr *to, unsigned int flags);
static void qrtr_handle_del_proc(struct sk_buff *skb);
static void qrtr_handle_del_proc(struct sk_buff *skb);
static void qrtr_cleanup_flow_control(struct qrtr_node *node,
				      struct sk_buff *skb);


static void qrtr_log_tx_msg(struct qrtr_node *node, struct qrtr_hdr_v1 *hdr,
static void qrtr_log_tx_msg(struct qrtr_node *node, struct qrtr_hdr_v1 *hdr,
			    struct sk_buff *skb)
			    struct sk_buff *skb)
@@ -1047,6 +1049,10 @@ static void qrtr_node_rx_work(struct kthread_work *work)
			if (!ipc) {
			if (!ipc) {
				kfree_skb(skb);
				kfree_skb(skb);
			} else {
			} else {
				if (cb->type == QRTR_TYPE_DEL_SERVER ||
				    cb->type == QRTR_TYPE_DEL_CLIENT) {
					qrtr_cleanup_flow_control(node, skb);
				}
				qrtr_sock_queue_skb(node, skb, ipc);
				qrtr_sock_queue_skb(node, skb, ipc);
				qrtr_port_put(ipc);
				qrtr_port_put(ipc);
			}
			}
@@ -1054,6 +1060,47 @@ static void qrtr_node_rx_work(struct kthread_work *work)
	}
	}
}
}


static void qrtr_cleanup_flow_control(struct qrtr_node *node,
				      struct sk_buff *skb)
{
	struct qrtr_ctrl_pkt *pkt;
	unsigned long key;
	struct sockaddr_qrtr src;
	struct qrtr_tx_flow *flow;
	struct qrtr_tx_flow_waiter *waiter;
	struct qrtr_tx_flow_waiter *temp;
	u32 cmd;

	pkt = (void *)skb->data;
	cmd = le32_to_cpu(pkt->cmd);

	if (cmd == QRTR_TYPE_DEL_SERVER) {
		src.sq_node = le32_to_cpu(pkt->server.node);
		src.sq_port = le32_to_cpu(pkt->server.port);
	} else {
		src.sq_node = le32_to_cpu(pkt->client.node);
		src.sq_port = le32_to_cpu(pkt->client.port);
	}

	key = (u64)src.sq_node << 32 | src.sq_port;

	mutex_lock(&node->qrtr_tx_lock);
	flow = radix_tree_lookup(&node->qrtr_tx_flow, key);
	if (!flow) {
		mutex_unlock(&node->qrtr_tx_lock);
		return;
	}

	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, key);
	mutex_unlock(&node->qrtr_tx_lock);
}

static void qrtr_handle_del_proc(struct sk_buff *skb)
static void qrtr_handle_del_proc(struct sk_buff *skb)
{
{
	struct sockaddr_qrtr src = {AF_QIPCRTR, 0, QRTR_PORT_CTRL};
	struct sockaddr_qrtr src = {AF_QIPCRTR, 0, QRTR_PORT_CTRL};