diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index b2bbe69b25543c5a355286ebb75750c6b5726e1c..b8670bf262e249dea10d463fb3b7d2e926ff747e 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -225,6 +225,17 @@ static void bclink_retransmit_pkt(u32 after, u32 to) tipc_link_retransmit(bcl, buf, mod(to - after)); } +/** + * tipc_bclink_wakeup_users - wake up pending users + * + * Called with no locks taken + */ +void tipc_bclink_wakeup_users(void) +{ + while (skb_queue_len(&bclink->link.waiting_sks)) + tipc_sk_rcv(skb_dequeue(&bclink->link.waiting_sks)); +} + /** * tipc_bclink_acknowledge - handle acknowledgement of broadcast packets * @n_ptr: node that sent acknowledgement info @@ -300,7 +311,8 @@ void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked) bclink_set_last_sent(); } if (unlikely(released && !skb_queue_empty(&bcl->waiting_sks))) - bclink->node.action_flags |= TIPC_WAKEUP_USERS; + n_ptr->action_flags |= TIPC_WAKEUP_BCAST_USERS; + exit: tipc_bclink_unlock(); } diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index 4875d9536aee7a98ea523b895b3be6475529d7bd..e7b0f85a82bc82a19573b0f3f4158814ba42b7bd 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h @@ -99,5 +99,5 @@ int tipc_bclink_set_queue_limits(u32 limit); void tipc_bcbearer_sort(struct tipc_node_map *nm_ptr, u32 node, bool action); uint tipc_bclink_get_mtu(void); int tipc_bclink_xmit(struct sk_buff *buf); - +void tipc_bclink_wakeup_users(void); #endif diff --git a/net/tipc/node.c b/net/tipc/node.c index 17e6378c4dfe479790d085916cb5bfe40b445ae9..90cee4a6fce49450a0f83cca53fcf663ebea8148 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -552,6 +552,7 @@ void tipc_node_unlock(struct tipc_node *node) LIST_HEAD(conn_sks); struct sk_buff_head waiting_sks; u32 addr = 0; + unsigned int flags = node->action_flags; if (likely(!node->action_flags)) { spin_unlock_bh(&node->lock); @@ -572,6 +573,7 @@ void tipc_node_unlock(struct tipc_node *node) node->action_flags &= ~TIPC_NOTIFY_NODE_UP; addr = node->addr; } + node->action_flags &= ~TIPC_WAKEUP_BCAST_USERS; spin_unlock_bh(&node->lock); while (!skb_queue_empty(&waiting_sks)) @@ -583,6 +585,9 @@ void tipc_node_unlock(struct tipc_node *node) if (!list_empty(&nsub_list)) tipc_nodesub_notify(&nsub_list); + if (flags & TIPC_WAKEUP_BCAST_USERS) + tipc_bclink_wakeup_users(); + if (addr) tipc_named_node_up(addr); } diff --git a/net/tipc/node.h b/net/tipc/node.h index 522d6f3157b32cb9aa2d28086700728216e17e81..67513c3c852c41f2d2a89ffc4d1eb22b7e77de91 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h @@ -59,7 +59,8 @@ enum { TIPC_WAIT_OWN_LINKS_DOWN = (1 << 2), TIPC_NOTIFY_NODE_DOWN = (1 << 3), TIPC_NOTIFY_NODE_UP = (1 << 4), - TIPC_WAKEUP_USERS = (1 << 5) + TIPC_WAKEUP_USERS = (1 << 5), + TIPC_WAKEUP_BCAST_USERS = (1 << 6) }; /**