In many cases the call order when a link is reset goes as follows:
tipc_node_xx()->tipc_link_reset()->tipc_node_link_down()
This is not the right order if we want the node to be in control,
so in this commit we change the order to:
tipc_node_xx()->tipc_node_link_down()->tipc_link_reset()
The fact that tipc_link_reset() now is called from only one
location with a well-defined state will also facilitate later
simplifications of tipc_link_reset() and the link FSM.
Tested-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
void tipc_link_reset(struct tipc_link *l_ptr)
{
u32 prev_state = l_ptr->state;
void tipc_link_reset(struct tipc_link *l_ptr)
{
u32 prev_state = l_ptr->state;
- int was_active_link = tipc_link_is_active(l_ptr);
struct tipc_node *owner = l_ptr->owner;
struct tipc_link *pl = tipc_parallel_link(l_ptr);
struct tipc_node *owner = l_ptr->owner;
struct tipc_link *pl = tipc_parallel_link(l_ptr);
(prev_state == TIPC_LINK_ESTABLISHING))
return;
(prev_state == TIPC_LINK_ESTABLISHING))
return;
- tipc_node_link_down(l_ptr->owner, l_ptr->bearer_id);
- tipc_bearer_remove_dest(owner->net, l_ptr->bearer_id, l_ptr->addr);
-
- if (was_active_link && tipc_node_is_up(l_ptr->owner) && (pl != l_ptr)) {
+ if (tipc_node_is_up(l_ptr->owner) && (pl != l_ptr)) {
l_ptr->exec_mode = TIPC_LINK_BLOCKED;
l_ptr->failover_checkpt = l_ptr->rcv_nxt;
pl->failover_pkts = FIRST_FAILOVER;
l_ptr->exec_mode = TIPC_LINK_BLOCKED;
l_ptr->failover_checkpt = l_ptr->rcv_nxt;
pl->failover_pkts = FIRST_FAILOVER;
tipc_node_calculate_timer(n, l);
rc = tipc_link_timeout(l, &xmitq);
if (rc & TIPC_LINK_DOWN_EVT)
tipc_node_calculate_timer(n, l);
rc = tipc_link_timeout(l, &xmitq);
if (rc & TIPC_LINK_DOWN_EVT)
+ tipc_node_link_down(n, bearer_id);
}
tipc_node_unlock(n);
maddr = &n->links[bearer_id].maddr;
}
tipc_node_unlock(n);
maddr = &n->links[bearer_id].maddr;
struct tipc_link *l, *_l;
l = n->links[bearer_id].link;
struct tipc_link *l, *_l;
l = n->links[bearer_id].link;
+ if (!l || !tipc_link_is_up(l))
+ return;
+
n->working_links--;
n->action_flags |= TIPC_NOTIFY_LINK_DOWN;
n->link_id = l->peer_bearer_id << 16 | l->bearer_id;
n->working_links--;
n->action_flags |= TIPC_NOTIFY_LINK_DOWN;
n->link_id = l->peer_bearer_id << 16 | l->bearer_id;
+ tipc_bearer_remove_dest(n->net, l->bearer_id, n->addr);
+
pr_debug("Lost link <%s> on network plane %c\n",
l->name, l->net_plane);
pr_debug("Lost link <%s> on network plane %c\n",
l->name, l->net_plane);
_l = n->links[i].link;
if (!_l || !tipc_link_is_up(_l))
continue;
_l = n->links[i].link;
if (!_l || !tipc_link_is_up(_l))
continue;
+ if (_l == l)
+ continue;
if (_l->priority < highest)
continue;
if (_l->priority > highest) {
if (_l->priority < highest)
continue;
if (_l->priority > highest) {
if (tipc_node_is_up(n))
tipc_link_failover_send_queue(l);
if (tipc_node_is_up(n))
tipc_link_failover_send_queue(l);
+
+ tipc_link_reset(l);
+
+ if (!tipc_node_is_up(n))
}
memcpy(&l->media_addr, maddr, sizeof(*maddr));
memcpy(curr, maddr, sizeof(*maddr));
}
memcpy(&l->media_addr, maddr, sizeof(*maddr));
memcpy(curr, maddr, sizeof(*maddr));
+ tipc_node_link_down(n, b->identity);
tipc_node_lock(n);
l = n->links[bearer_id].link;
if (l) {
tipc_node_lock(n);
l = n->links[bearer_id].link;
if (l) {
+ tipc_node_link_down(n, bearer_id);
n->links[bearer_id].link = NULL;
n->link_cnt--;
}
n->links[bearer_id].link = NULL;
n->link_cnt--;
}
tipc_addr_string_fill(addr_string, n->addr));
for (i = 0; i < MAX_BEARERS; i++) {
tipc_addr_string_fill(addr_string, n->addr));
for (i = 0; i < MAX_BEARERS; i++) {
- if (n->links[i].link)
- tipc_link_reset(n->links[i].link);
+ if (!n->links[i].link)
+ continue;
+ tipc_node_link_down(n, i);
if (likely(l))
rc = tipc_link_xmit(l, list, &xmitq);
if (unlikely(rc == -ENOBUFS))
if (likely(l))
rc = tipc_link_xmit(l, list, &xmitq);
if (unlikely(rc == -ENOBUFS))
+ tipc_node_link_down(n, bearer_id);
tipc_node_unlock(n);
tipc_node_put(n);
}
tipc_node_unlock(n);
tipc_node_put(n);
}
if (msg_type(hdr) == FAILOVER_MSG) {
if (tipc_link_is_up(pl)) {
if (msg_type(hdr) == FAILOVER_MSG) {
if (tipc_link_is_up(pl)) {
+ tipc_node_link_down(n, pb_id);
pl->exec_mode = TIPC_LINK_BLOCKED;
}
}
pl->exec_mode = TIPC_LINK_BLOCKED;
}
}
if (unlikely(rc & TIPC_LINK_UP_EVT))
tipc_node_link_up(n, bearer_id);
if (unlikely(rc & TIPC_LINK_DOWN_EVT))
if (unlikely(rc & TIPC_LINK_UP_EVT))
tipc_node_link_up(n, bearer_id);
if (unlikely(rc & TIPC_LINK_DOWN_EVT))
+ tipc_node_link_down(n, bearer_id);
skb = NULL;
unlock:
tipc_node_unlock(n);
skb = NULL;
unlock:
tipc_node_unlock(n);