summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/tipc/bearer.c8
-rw-r--r--net/tipc/link.c12
-rw-r--r--net/tipc/link.h1
-rw-r--r--net/tipc/node.c5
-rw-r--r--net/tipc/udp_media.c1
5 files changed, 19 insertions, 8 deletions
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index ce9f7bfc0b92..82b278668ab7 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -362,6 +362,7 @@ static void bearer_disable(struct net *net, struct tipc_bearer *b_ptr)
b_ptr->media->disable_media(b_ptr);
tipc_node_delete_links(net, b_ptr->identity);
+ RCU_INIT_POINTER(b_ptr->media_ptr, NULL);
if (b_ptr->link_req)
tipc_disc_delete(b_ptr->link_req);
@@ -399,16 +400,13 @@ int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b,
/* tipc_disable_l2_media - detach TIPC bearer from an L2 interface
*
- * Mark L2 bearer as inactive so that incoming buffers are thrown away,
- * then get worker thread to complete bearer cleanup. (Can't do cleanup
- * here because cleanup code needs to sleep and caller holds spinlocks.)
+ * Mark L2 bearer as inactive so that incoming buffers are thrown away
*/
void tipc_disable_l2_media(struct tipc_bearer *b)
{
struct net_device *dev;
dev = (struct net_device *)rtnl_dereference(b->media_ptr);
- RCU_INIT_POINTER(b->media_ptr, NULL);
RCU_INIT_POINTER(dev->tipc_ptr, NULL);
synchronize_net();
dev_put(dev);
@@ -554,7 +552,7 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
case NETDEV_CHANGE:
if (netif_carrier_ok(dev))
break;
- case NETDEV_DOWN:
+ case NETDEV_GOING_DOWN:
case NETDEV_CHANGEMTU:
tipc_reset_bearer(net, b_ptr);
break;
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 8c794c1dd531..737b5980020d 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1062,6 +1062,18 @@ void tipc_link_build_ack_msg(struct tipc_link *l, struct sk_buff_head *xmitq)
tipc_link_build_proto_msg(l, STATE_MSG, 0, 0, 0, 0, xmitq);
}
+/* tipc_link_build_reset_msg: prepare link RESET or ACTIVATE message
+ */
+void tipc_link_build_reset_msg(struct tipc_link *l, struct sk_buff_head *xmitq)
+{
+ int mtyp = RESET_MSG;
+
+ if (l->state == LINK_ESTABLISHING)
+ mtyp = ACTIVATE_MSG;
+
+ tipc_link_build_proto_msg(l, mtyp, 0, 0, 0, 0, xmitq);
+}
+
/* tipc_link_build_nack_msg: prepare link nack message for transmission
*/
static void tipc_link_build_nack_msg(struct tipc_link *l,
diff --git a/net/tipc/link.h b/net/tipc/link.h
index d42dfc0e7bf5..5872f090c8d8 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -213,6 +213,7 @@ void tipc_link_tnl_prepare(struct tipc_link *l, struct tipc_link *tnl,
int mtyp, struct sk_buff_head *xmitq);
void tipc_link_build_bcast_sync_msg(struct tipc_link *l,
struct sk_buff_head *xmitq);
+void tipc_link_build_reset_msg(struct tipc_link *l, struct sk_buff_head *xmitq);
int tipc_link_fsm_evt(struct tipc_link *l, int evt);
void tipc_link_reset_fragments(struct tipc_link *l_ptr);
bool tipc_link_is_up(struct tipc_link *l);
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 656b5791f1a5..fba6e1af28e8 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -41,7 +41,7 @@
#include "socket.h"
#include "bcast.h"
#include "discover.h"
-
+#define pr_debug printk
/* Node FSM states and events:
*/
enum {
@@ -421,6 +421,8 @@ static void __tipc_node_link_down(struct tipc_node *n, int *bearer_id,
if (!tipc_node_is_up(n)) {
tipc_link_reset(l);
+ tipc_link_build_reset_msg(l, xmitq);
+ *maddr = &n->links[*bearer_id].maddr;
node_lost_contact(n, &le->inputq);
return;
}
@@ -463,7 +465,6 @@ static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete)
tipc_link_fsm_evt(l, LINK_RESET_EVT);
}
tipc_node_unlock(n);
-
tipc_bearer_xmit(n->net, bearer_id, &xmitq, maddr);
tipc_sk_rcv(n->net, &le->inputq);
}
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c
index c170d3138953..9bc0b1e515fa 100644
--- a/net/tipc/udp_media.c
+++ b/net/tipc/udp_media.c
@@ -425,7 +425,6 @@ static void tipc_udp_disable(struct tipc_bearer *b)
}
if (ub->ubsock)
sock_set_flag(ub->ubsock->sk, SOCK_DEAD);
- RCU_INIT_POINTER(b->media_ptr, NULL);
RCU_INIT_POINTER(ub->bearer, NULL);
/* sock_release need to be done outside of rtnl lock */