mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
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: Loic Poulain <loic.poulain@linaro.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
f7dec6cb91
commit
90829f07ba
@ -171,8 +171,13 @@ static void __qrtr_node_release(struct kref *kref)
|
||||
void __rcu **slot;
|
||||
|
||||
spin_lock_irqsave(&qrtr_nodes_lock, flags);
|
||||
if (node->nid != QRTR_EP_NID_AUTO)
|
||||
radix_tree_delete(&qrtr_nodes, node->nid);
|
||||
/* If the node is a bridge for other nodes, there are possibly
|
||||
* 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);
|
||||
|
||||
list_del(&node->item);
|
||||
@ -602,6 +607,7 @@ void qrtr_endpoint_unregister(struct qrtr_endpoint *ep)
|
||||
struct qrtr_ctrl_pkt *pkt;
|
||||
struct qrtr_tx_flow *flow;
|
||||
struct sk_buff *skb;
|
||||
unsigned long flags;
|
||||
void __rcu **slot;
|
||||
|
||||
mutex_lock(&node->ep_lock);
|
||||
@ -609,11 +615,18 @@ void qrtr_endpoint_unregister(struct qrtr_endpoint *ep)
|
||||
mutex_unlock(&node->ep_lock);
|
||||
|
||||
/* Notify the local controller about the event */
|
||||
skb = qrtr_alloc_ctrl_packet(&pkt, GFP_KERNEL);
|
||||
if (skb) {
|
||||
pkt->cmd = cpu_to_le32(QRTR_TYPE_BYE);
|
||||
qrtr_local_enqueue(NULL, skb, QRTR_TYPE_BYE, &src, &dst);
|
||||
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) {
|
||||
pkt->cmd = cpu_to_le32(QRTR_TYPE_BYE);
|
||||
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 */
|
||||
mutex_lock(&node->qrtr_tx_lock);
|
||||
|
Loading…
Reference in New Issue
Block a user