diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 4931eea65797b4ac73810090b1c65d12e7377bc7..60caa45e5a416344c22fda90900b98e89be47384 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -51,7 +51,7 @@ static struct tipc_media * const media_info_array[] = {
 
 struct tipc_bearer tipc_bearers[MAX_BEARERS];
 
-static void bearer_disable(struct tipc_bearer *b_ptr);
+static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down);
 
 /**
  * tipc_media_find - locates specified media object by name
@@ -331,7 +331,7 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority)
 
 	res = tipc_disc_create(b_ptr, &b_ptr->bcast_addr, disc_domain);
 	if (res) {
-		bearer_disable(b_ptr);
+		bearer_disable(b_ptr, false);
 		pr_warn("Bearer <%s> rejected, discovery object creation failed\n",
 			name);
 		goto exit;
@@ -363,14 +363,14 @@ static int tipc_reset_bearer(struct tipc_bearer *b_ptr)
  *
  * Note: This routine assumes caller holds tipc_net_lock.
  */
-static void bearer_disable(struct tipc_bearer *b_ptr)
+static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down)
 {
 	struct tipc_link_req *temp_req;
 
 	pr_info("Disabling bearer <%s>\n", b_ptr->name);
 	spin_lock_bh(&b_ptr->lock);
 	b_ptr->media->disable_media(b_ptr);
-	tipc_link_delete_list(b_ptr->identity);
+	tipc_link_delete_list(b_ptr->identity, shutting_down);
 	temp_req = b_ptr->link_req;
 	b_ptr->link_req = NULL;
 	spin_unlock_bh(&b_ptr->lock);
@@ -392,7 +392,7 @@ int tipc_disable_bearer(const char *name)
 		pr_warn("Attempt to disable unknown bearer <%s>\n", name);
 		res = -EINVAL;
 	} else {
-		bearer_disable(b_ptr);
+		bearer_disable(b_ptr, false);
 		res = 0;
 	}
 	write_unlock_bh(&tipc_net_lock);
@@ -612,6 +612,6 @@ void tipc_bearer_stop(void)
 
 	for (i = 0; i < MAX_BEARERS; i++) {
 		if (tipc_bearers[i].active)
-			bearer_disable(&tipc_bearers[i]);
+			bearer_disable(&tipc_bearers[i], true);
 	}
 }
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 663623c5896df20098f9efe3f981a1d7338dc155..03075165665ee9e19f6bfae2f6adf508e82744ba 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -281,7 +281,7 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
 }
 
 
-void tipc_link_delete_list(unsigned int bearer_id)
+void tipc_link_delete_list(unsigned int bearer_id, bool shutting_down)
 {
 	struct tipc_link *l_ptr;
 	struct tipc_node *n_ptr;
@@ -291,12 +291,20 @@ void tipc_link_delete_list(unsigned int bearer_id)
 		l_ptr = n_ptr->links[bearer_id];
 		if (l_ptr) {
 			tipc_link_reset(l_ptr);
-			tipc_node_detach_link(n_ptr, l_ptr);
-			spin_unlock_bh(&n_ptr->lock);
-
-			/* Nobody else can access this link now: */
-			del_timer_sync(&l_ptr->timer);
-			kfree(l_ptr);
+			if (shutting_down || !tipc_node_is_up(n_ptr)) {
+				tipc_node_detach_link(l_ptr->owner, l_ptr);
+				tipc_link_reset_fragments(l_ptr);
+				spin_unlock_bh(&n_ptr->lock);
+
+				/* Nobody else can access this link now: */
+				del_timer_sync(&l_ptr->timer);
+				kfree(l_ptr);
+			} else {
+				/* Detach/delete when failover is finished: */
+				l_ptr->flags |= LINK_STOPPED;
+				spin_unlock_bh(&n_ptr->lock);
+				del_timer_sync(&l_ptr->timer);
+			}
 			continue;
 		}
 		spin_unlock_bh(&n_ptr->lock);
@@ -481,6 +489,9 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
 	struct tipc_link *other;
 	u32 cont_intv = l_ptr->continuity_interval;
 
+	if (l_ptr->flags & LINK_STOPPED)
+		return;
+
 	if (!(l_ptr->flags & LINK_STARTED) && (event != STARTING_EVT))
 		return;		/* Not yet. */
 
@@ -2167,8 +2178,11 @@ static struct sk_buff *tipc_link_failover_rcv(struct tipc_link *l_ptr,
 					   &buf);
 		}
 	}
-
 exit:
+	if ((l_ptr->exp_msg_count == 0) && (l_ptr->flags & LINK_STOPPED)) {
+		tipc_node_detach_link(l_ptr->owner, l_ptr);
+		kfree(l_ptr);
+	}
 	return buf;
 }
 
@@ -2201,7 +2215,6 @@ static int tipc_link_tunnel_rcv(struct tipc_node *n_ptr,
 		*buf = tipc_link_failover_rcv(l_ptr, t_buf);
 	else
 		pr_warn("%sunknown tunnel pkt received\n", link_co_err);
-
 exit:
 	kfree_skb(t_buf);
 	return *buf != NULL;
diff --git a/net/tipc/link.h b/net/tipc/link.h
index 3340fc1fc299a3c6347e33c3a5fc7ed4fe256ec6..45b9cd071c41bd8ce0bc18897b019f1760c404f2 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -214,7 +214,7 @@ struct tipc_port;
 struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
 			      struct tipc_bearer *b_ptr,
 			      const struct tipc_media_addr *media_addr);
-void tipc_link_delete_list(unsigned int bearer_id);
+void tipc_link_delete_list(unsigned int bearer_id, bool shutting_down);
 void tipc_link_failover_send_queue(struct tipc_link *l_ptr);
 void tipc_link_dup_send_queue(struct tipc_link *l_ptr,
 			      struct tipc_link *dest);
diff --git a/net/tipc/node.c b/net/tipc/node.c
index efe4d41bf11bacb258e3096dc4619e97828c2904..833324b73fe129054993344800946b9e671b6fae 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -249,7 +249,13 @@ void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
 
 void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
 {
-	n_ptr->links[l_ptr->b_ptr->identity] = NULL;
+	int i;
+
+	for (i = 0; i < MAX_BEARERS; i++) {
+		if (l_ptr == n_ptr->links[i])
+			break;
+	}
+	n_ptr->links[i] = NULL;
 	atomic_dec(&tipc_num_links);
 	n_ptr->link_cnt--;
 }