Commit 90829f07 authored by Loic Poulain's avatar Loic Poulain Committed by Jakub Kicinski

net: qrtr: Release distant nodes along the bridge node

Distant QRTR nodes can be accessed via an other node that acts as
a bridge. When the a QRTR endpoint associated to a bridge node is
released, all the linked distant nodes should also be released.

This patch fixes endpoint release by:
- Submitting QRTR BYE message locally on behalf of all the nodes
accessible through the endpoint.
- Removing all the routable node IDs from radix tree pointing to
the released node endpoint.
Signed-off-by: default avatarLoic Poulain <loic.poulain@linaro.org>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent f7dec6cb
...@@ -171,8 +171,13 @@ static void __qrtr_node_release(struct kref *kref) ...@@ -171,8 +171,13 @@ static void __qrtr_node_release(struct kref *kref)
void __rcu **slot; void __rcu **slot;
spin_lock_irqsave(&qrtr_nodes_lock, flags); spin_lock_irqsave(&qrtr_nodes_lock, flags);
if (node->nid != QRTR_EP_NID_AUTO) /* If the node is a bridge for other nodes, there are possibly
radix_tree_delete(&qrtr_nodes, node->nid); * multiple entries pointing to our released node, delete them all.
*/
radix_tree_for_each_slot(slot, &qrtr_nodes, &iter, 0) {
if (*slot == node)
radix_tree_iter_delete(&qrtr_nodes, &iter, slot);
}
spin_unlock_irqrestore(&qrtr_nodes_lock, flags); spin_unlock_irqrestore(&qrtr_nodes_lock, flags);
list_del(&node->item); list_del(&node->item);
...@@ -602,6 +607,7 @@ void qrtr_endpoint_unregister(struct qrtr_endpoint *ep) ...@@ -602,6 +607,7 @@ void qrtr_endpoint_unregister(struct qrtr_endpoint *ep)
struct qrtr_ctrl_pkt *pkt; struct qrtr_ctrl_pkt *pkt;
struct qrtr_tx_flow *flow; struct qrtr_tx_flow *flow;
struct sk_buff *skb; struct sk_buff *skb;
unsigned long flags;
void __rcu **slot; void __rcu **slot;
mutex_lock(&node->ep_lock); mutex_lock(&node->ep_lock);
...@@ -609,11 +615,18 @@ void qrtr_endpoint_unregister(struct qrtr_endpoint *ep) ...@@ -609,11 +615,18 @@ void qrtr_endpoint_unregister(struct qrtr_endpoint *ep)
mutex_unlock(&node->ep_lock); mutex_unlock(&node->ep_lock);
/* Notify the local controller about the event */ /* Notify the local controller about the event */
skb = qrtr_alloc_ctrl_packet(&pkt, GFP_KERNEL); spin_lock_irqsave(&qrtr_nodes_lock, flags);
radix_tree_for_each_slot(slot, &qrtr_nodes, &iter, 0) {
if (*slot != node)
continue;
src.sq_node = iter.index;
skb = qrtr_alloc_ctrl_packet(&pkt, GFP_ATOMIC);
if (skb) { if (skb) {
pkt->cmd = cpu_to_le32(QRTR_TYPE_BYE); pkt->cmd = cpu_to_le32(QRTR_TYPE_BYE);
qrtr_local_enqueue(NULL, skb, QRTR_TYPE_BYE, &src, &dst); qrtr_local_enqueue(NULL, skb, QRTR_TYPE_BYE, &src, &dst);
} }
}
spin_unlock_irqrestore(&qrtr_nodes_lock, flags);
/* Wake up any transmitters waiting for resume-tx from the node */ /* Wake up any transmitters waiting for resume-tx from the node */
mutex_lock(&node->qrtr_tx_lock); mutex_lock(&node->qrtr_tx_lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment