From 271d7f749079d619a81fe50314811ca0d56abfe4 Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Mon, 3 Oct 2022 09:58:15 -0700 Subject: [PATCH 1/4] net: qrtr: Rename qrtr_all_nodes to qrtr_all_epts The node list only respresents the adjacent nodes in the system. Rename the list to qrtr_all_epts to better describe the list contents. Rename qrtr_nodes_lock to qrtr_epts_lock to better describe lock. Change-Id: I168ca597d5b9b30d6c064c2a56b6e8b2dffa387b Signed-off-by: Chris Lew --- net/qrtr/af_qrtr.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c index 28b6fc6d5ccb..1828ac1ac131 100644 --- a/net/qrtr/af_qrtr.c +++ b/net/qrtr/af_qrtr.c @@ -111,9 +111,9 @@ static unsigned int qrtr_local_nid = 1; static RADIX_TREE(qrtr_nodes, GFP_ATOMIC); static DEFINE_SPINLOCK(qrtr_nodes_lock); /* broadcast list */ -static LIST_HEAD(qrtr_all_nodes); -/* lock for qrtr_all_nodes and node reference */ -static DECLARE_RWSEM(qrtr_node_lock); +static LIST_HEAD(qrtr_all_epts); +/* lock for qrtr_all_epts */ +static DECLARE_RWSEM(qrtr_epts_lock); /* local port allocation management */ static DEFINE_XARRAY_ALLOC(qrtr_ports); @@ -219,7 +219,7 @@ static void __qrtr_node_release(struct kref *kref) spin_unlock_irqrestore(&qrtr_nodes_lock, flags); list_del(&node->item); - up_write(&qrtr_node_lock); + up_write(&qrtr_epts_lock); skb_queue_purge(&node->rx_queue); @@ -245,7 +245,7 @@ static void qrtr_node_release(struct qrtr_node *node) { if (!node) return; - kref_put_rwsem_lock(&node->ref, __qrtr_node_release, &qrtr_node_lock); + kref_put_rwsem_lock(&node->ref, __qrtr_node_release, &qrtr_epts_lock); } /** @@ -649,9 +649,9 @@ int qrtr_endpoint_register(struct qrtr_endpoint *ep, unsigned int nid) qrtr_node_assign(node, nid); - down_write(&qrtr_node_lock); - list_add(&node->item, &qrtr_all_nodes); - up_write(&qrtr_node_lock); + down_write(&qrtr_epts_lock); + list_add(&node->item, &qrtr_all_epts); + up_write(&qrtr_epts_lock); ep->node = node; return 0; @@ -969,17 +969,18 @@ static int qrtr_bcast_enqueue(struct qrtr_node *node, struct sk_buff *skb, { struct sk_buff *skbn; - down_read(&qrtr_node_lock); - list_for_each_entry(node, &qrtr_all_nodes, item) { + down_read(&qrtr_epts_lock); + list_for_each_entry(node, &qrtr_all_epts, item) { if (node->nid == QRTR_EP_NID_AUTO) continue; + skbn = skb_clone(skb, GFP_KERNEL); if (!skbn) break; skb_set_owner_w(skbn, skb->sk); qrtr_node_enqueue(node, skbn, type, from, to); } - up_read(&qrtr_node_lock); + up_read(&qrtr_epts_lock); qrtr_local_enqueue(NULL, skb, type, from, to); From e1a8c77a3e090b6f39dfcf1599c4f5757ac715c4 Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Mon, 3 Oct 2022 09:58:21 -0700 Subject: [PATCH 2/4] net: qrtr: Add missing reference cleanup Add missing node reference put when memory allocation fails for the tx_resume packet. Without this there could be dangling references to a node. Change-Id: I5a5dfa437243a39d3da660251c0357ff6eb6cbff Signed-off-by: Chris Lew --- net/qrtr/af_qrtr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c index 1828ac1ac131..63d7e336a88e 100644 --- a/net/qrtr/af_qrtr.c +++ b/net/qrtr/af_qrtr.c @@ -1113,8 +1113,10 @@ static int qrtr_send_resume_tx(struct qrtr_cb *cb) return -EINVAL; skb = qrtr_alloc_ctrl_packet(&pkt, GFP_KERNEL); - if (!skb) + if (!skb) { + qrtr_node_release(node); return -ENOMEM; + } pkt->cmd = cpu_to_le32(QRTR_TYPE_RESUME_TX); pkt->client.node = cpu_to_le32(cb->dst_node); From efcd1d175bbe0beac2ec7ec246952a79d88996ee Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Mon, 3 Oct 2022 09:58:31 -0700 Subject: [PATCH 3/4] net: qrtr: Return -ENODEV error code if port not found Post function is called from interrupt context. Returning same error code in all cases rsults in excessive prints which can cause irq throttling. Return -ENODEV when port lookup fails in post function. CRs-Fixed: 2790559 Change-Id: I75384b2116cb2fe1bbeaa2dac91157345f0bab54 Signed-off-by: Deepak Kumar Singh Signed-off-by: Jay Jayanna Signed-off-by: Chris Lew --- net/qrtr/af_qrtr.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c index 63d7e336a88e..fe5d9cb49e85 100644 --- a/net/qrtr/af_qrtr.c +++ b/net/qrtr/af_qrtr.c @@ -572,8 +572,10 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) qrtr_tx_resume(node, skb); } else { ipc = qrtr_port_lookup(cb->dst_port); - if (!ipc) - goto err; + if (!ipc) { + kfree_skb(skb); + return -ENODEV; + } if (sock_queue_rcv_skb(&ipc->sk, skb)) { qrtr_port_put(ipc); From a51c4125245bea5fafa6e55ba17d826400415bb7 Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Mon, 3 Oct 2022 09:58:46 -0700 Subject: [PATCH 4/4] net: qrtr: Do not take sock lock on blocking recv Socket client's should be able to block on recv without blocking other socket operations such as sending. The qrtr core logic should also be able to operate on the sock while a client is blocked in recv. Remove the sock lock from around the recv_datagram to allow execution to continue while a client is blocked in recv. Change-Id: I6adb09b8e44c5ff3542b88db87b376a3ae5cb5ba Signed-off-by: Jay Jayanna Signed-off-by: Chris Lew --- net/qrtr/af_qrtr.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c index fe5d9cb49e85..099a36887a5d 100644 --- a/net/qrtr/af_qrtr.c +++ b/net/qrtr/af_qrtr.c @@ -1140,18 +1140,15 @@ static int qrtr_recvmsg(struct socket *sock, struct msghdr *msg, struct qrtr_cb *cb; int copied, rc; - lock_sock(sk); - if (sock_flag(sk, SOCK_ZAPPED)) { - release_sock(sk); + if (sock_flag(sk, SOCK_ZAPPED)) return -EADDRNOTAVAIL; - } skb = skb_recv_datagram(sk, flags, &rc); - if (!skb) { - release_sock(sk); + if (!skb) return rc; - } + + lock_sock(sk); cb = (struct qrtr_cb *)skb->cb; copied = skb->len;