mmc: s3c6410: enable ADMA feature in 6410 sdhci controller
[safe/jmp/linux-2.6] / net / tipc / link.c
index 1b17fec..a3616b9 100644 (file)
 
 
 /*
+ * Out-of-range value for link session numbers
+ */
+
+#define INVALID_SESSION 0x10000
+
+/*
  * Limit for deferred reception queue:
  */
 
@@ -147,9 +153,21 @@ static void link_print(struct link *l_ptr, struct print_buf *buf,
 
 #define LINK_LOG_BUF_SIZE 0
 
-#define dbg_link(fmt, arg...)  do {if (LINK_LOG_BUF_SIZE) tipc_printf(&l_ptr->print_buf, fmt, ## arg); } while(0)
-#define dbg_link_msg(msg, txt) do {if (LINK_LOG_BUF_SIZE) tipc_msg_print(&l_ptr->print_buf, msg, txt); } while(0)
-#define dbg_link_state(txt) do {if (LINK_LOG_BUF_SIZE) link_print(l_ptr, &l_ptr->print_buf, txt); } while(0)
+#define dbg_link(fmt, arg...) \
+       do { \
+               if (LINK_LOG_BUF_SIZE) \
+                       tipc_printf(&l_ptr->print_buf, fmt, ## arg); \
+       } while (0)
+#define dbg_link_msg(msg, txt) \
+       do { \
+               if (LINK_LOG_BUF_SIZE) \
+                       tipc_msg_dbg(&l_ptr->print_buf, msg, txt); \
+       } while (0)
+#define dbg_link_state(txt) \
+       do { \
+               if (LINK_LOG_BUF_SIZE) \
+                       link_print(l_ptr, &l_ptr->print_buf, txt); \
+       } while (0)
 #define dbg_link_dump() do { \
        if (LINK_LOG_BUF_SIZE) { \
                tipc_printf(LOG, "\n\nDumping link <%s>:\n", l_ptr->name); \
@@ -184,41 +202,6 @@ static unsigned int align(unsigned int i)
        return (i + 3) & ~3u;
 }
 
-static int link_working_working(struct link *l_ptr)
-{
-       return (l_ptr->state == WORKING_WORKING);
-}
-
-static int link_working_unknown(struct link *l_ptr)
-{
-       return (l_ptr->state == WORKING_UNKNOWN);
-}
-
-static int link_reset_unknown(struct link *l_ptr)
-{
-       return (l_ptr->state == RESET_UNKNOWN);
-}
-
-static int link_reset_reset(struct link *l_ptr)
-{
-       return (l_ptr->state == RESET_RESET);
-}
-
-static int link_blocked(struct link *l_ptr)
-{
-       return (l_ptr->exp_msg_count || l_ptr->blocked);
-}
-
-static int link_congested(struct link *l_ptr)
-{
-       return (l_ptr->out_queue_size >= l_ptr->queue_limit[0]);
-}
-
-static u32 link_max_pkt(struct link *l_ptr)
-{
-       return l_ptr->max_pkt;
-}
-
 static void link_init_max_pkt(struct link *l_ptr)
 {
        u32 max_pkt;
@@ -360,8 +343,8 @@ static void link_timeout(struct link *l_ptr)
                struct tipc_msg *msg = buf_msg(l_ptr->first_out);
                u32 length = msg_size(msg);
 
-               if ((msg_user(msg) == MSG_FRAGMENTER)
-                   && (msg_type(msg) == FIRST_FRAGMENT)) {
+               if ((msg_user(msg) == MSG_FRAGMENTER) &&
+                   (msg_type(msg) == FIRST_FRAGMENT)) {
                        length = msg_size(msg_get_wrapped(msg));
                }
                if (length) {
@@ -450,9 +433,9 @@ struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer,
 
        l_ptr->pmsg = (struct tipc_msg *)&l_ptr->proto_msg;
        msg = l_ptr->pmsg;
-       msg_init(msg, LINK_PROTOCOL, RESET_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr);
+       tipc_msg_init(msg, LINK_PROTOCOL, RESET_MSG, INT_H_SIZE, l_ptr->addr);
        msg_set_size(msg, sizeof(l_ptr->proto_msg));
-       msg_set_session(msg, tipc_random);
+       msg_set_session(msg, (tipc_random & 0xffff));
        msg_set_bearer_id(msg, b_ptr->identity);
        strcpy((char *)msg_data(msg), if_name);
 
@@ -543,9 +526,8 @@ static int link_schedule_port(struct link *l_ptr, u32 origport, u32 sz)
                        goto exit;
                if (!list_empty(&p_ptr->wait_list))
                        goto exit;
-               p_ptr->congested_link = l_ptr;
                p_ptr->publ.congested = 1;
-               p_ptr->waiting_pkts = 1 + ((sz - 1) / link_max_pkt(l_ptr));
+               p_ptr->waiting_pkts = 1 + ((sz - 1) / l_ptr->max_pkt);
                list_add_tail(&p_ptr->wait_list, &l_ptr->waiting_ports);
                l_ptr->stats.link_congs++;
 exit:
@@ -574,7 +556,6 @@ void tipc_link_wakeup_ports(struct link *l_ptr, int all)
                if (win <= 0)
                        break;
                list_del_init(&p_ptr->wait_list);
-               p_ptr->congested_link = NULL;
                spin_lock_bh(p_ptr->publ.lock);
                p_ptr->publ.congested = 0;
                p_ptr->wakeup(&p_ptr->publ);
@@ -693,10 +674,10 @@ void tipc_link_reset(struct link *l_ptr)
        u32 checkpoint = l_ptr->next_in_no;
        int was_active_link = tipc_link_is_active(l_ptr);
 
-       msg_set_session(l_ptr->pmsg, msg_session(l_ptr->pmsg) + 1);
+       msg_set_session(l_ptr->pmsg, ((msg_session(l_ptr->pmsg) + 1) & 0xffff));
 
-       /* Link is down, accept any session: */
-       l_ptr->peer_session = 0;
+       /* Link is down, accept any session */
+       l_ptr->peer_session = INVALID_SESSION;
 
        /* Prepare for max packet size negotiation */
        link_init_max_pkt(l_ptr);
@@ -859,7 +840,7 @@ static void link_state_event(struct link *l_ptr, unsigned event)
                case TIMEOUT_EVT:
                        dbg_link("TIM ");
                        if (l_ptr->next_in_no != l_ptr->checkpoint) {
-                               dbg_link("-> WW \n");
+                               dbg_link("-> WW\n");
                                l_ptr->state = WORKING_WORKING;
                                l_ptr->fsm_msg_cnt = 0;
                                l_ptr->checkpoint = l_ptr->next_in_no;
@@ -916,7 +897,7 @@ static void link_state_event(struct link *l_ptr, unsigned event)
                        link_set_timer(l_ptr, cont_intv);
                        break;
                case RESET_MSG:
-                       dbg_link("RES \n");
+                       dbg_link("RES\n");
                        dbg_link(" -> RR\n");
                        l_ptr->state = RESET_RESET;
                        l_ptr->fsm_msg_cnt = 0;
@@ -929,7 +910,7 @@ static void link_state_event(struct link *l_ptr, unsigned event)
                        l_ptr->started = 1;
                        /* fall through */
                case TIMEOUT_EVT:
-                       dbg_link("TIM \n");
+                       dbg_link("TIM\n");
                        tipc_link_send_proto_msg(l_ptr, RESET_MSG, 0, 0, 0, 0, 0);
                        l_ptr->fsm_msg_cnt++;
                        link_set_timer(l_ptr, cont_intv);
@@ -999,7 +980,7 @@ static int link_bundle_buf(struct link *l_ptr,
                return 0;
        if (skb_tailroom(bundler) < (pad + size))
                return 0;
-       if (link_max_pkt(l_ptr) < (to_pos + size))
+       if (l_ptr->max_pkt < (to_pos + size))
                return 0;
 
        skb_put(bundler, pad + size);
@@ -1044,9 +1025,9 @@ int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf)
        u32 size = msg_size(msg);
        u32 dsz = msg_data_sz(msg);
        u32 queue_size = l_ptr->out_queue_size;
-       u32 imp = msg_tot_importance(msg);
+       u32 imp = tipc_msg_tot_importance(msg);
        u32 queue_limit = l_ptr->queue_limit[imp];
-       u32 max_packet = link_max_pkt(l_ptr);
+       u32 max_packet = l_ptr->max_pkt;
 
        msg_set_prevnode(msg, tipc_own_addr);   /* If routed message */
 
@@ -1109,8 +1090,8 @@ int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf)
                        struct tipc_msg bundler_hdr;
 
                        if (bundler) {
-                               msg_init(&bundler_hdr, MSG_BUNDLER, OPEN_MSG,
-                                        TIPC_OK, INT_H_SIZE, l_ptr->addr);
+                               tipc_msg_init(&bundler_hdr, MSG_BUNDLER, OPEN_MSG,
+                                        INT_H_SIZE, l_ptr->addr);
                                skb_copy_to_linear_data(bundler, &bundler_hdr,
                                                        INT_H_SIZE);
                                skb_trim(bundler, INT_H_SIZE);
@@ -1137,7 +1118,7 @@ int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf)
 int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector)
 {
        struct link *l_ptr;
-       struct node *n_ptr;
+       struct tipc_node *n_ptr;
        int res = -ELINKCONG;
 
        read_lock_bh(&tipc_net_lock);
@@ -1177,7 +1158,7 @@ static int link_send_buf_fast(struct link *l_ptr, struct sk_buff *buf,
        int res = msg_data_sz(msg);
 
        if (likely(!link_congested(l_ptr))) {
-               if (likely(msg_size(msg) <= link_max_pkt(l_ptr))) {
+               if (likely(msg_size(msg) <= l_ptr->max_pkt)) {
                        if (likely(list_empty(&l_ptr->b_ptr->cong_links))) {
                                link_add_to_outqueue(l_ptr, buf, msg);
                                if (likely(tipc_bearer_send(l_ptr->b_ptr, buf,
@@ -1194,7 +1175,7 @@ static int link_send_buf_fast(struct link *l_ptr, struct sk_buff *buf,
                        }
                }
                else
-                       *used_max_pkt = link_max_pkt(l_ptr);
+                       *used_max_pkt = l_ptr->max_pkt;
        }
        return tipc_link_send_buf(l_ptr, buf);  /* All other cases */
 }
@@ -1208,7 +1189,7 @@ static int link_send_buf_fast(struct link *l_ptr, struct sk_buff *buf,
 int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode)
 {
        struct link *l_ptr;
-       struct node *n_ptr;
+       struct tipc_node *n_ptr;
        int res;
        u32 selector = msg_origport(buf_msg(buf)) & 1;
        u32 dummy;
@@ -1252,7 +1233,7 @@ int tipc_link_send_sections_fast(struct port *sender,
        struct tipc_msg *hdr = &sender->publ.phdr;
        struct link *l_ptr;
        struct sk_buff *buf;
-       struct node *node;
+       struct tipc_node *node;
        int res;
        u32 selector = msg_origport(hdr) & 1;
 
@@ -1262,7 +1243,7 @@ again:
         * (Must not hold any locks while building message.)
         */
 
-       res = msg_build(hdr, msg_sect, num_sect, sender->publ.max_pkt,
+       res = tipc_msg_build(hdr, msg_sect, num_sect, sender->publ.max_pkt,
                        !sender->user_port, &buf);
 
        read_lock_bh(&tipc_net_lock);
@@ -1301,7 +1282,7 @@ exit:
                         * then re-try fast path or fragment the message
                         */
 
-                       sender->publ.max_pkt = link_max_pkt(l_ptr);
+                       sender->publ.max_pkt = l_ptr->max_pkt;
                        tipc_node_unlock(node);
                        read_unlock_bh(&tipc_net_lock);
 
@@ -1346,7 +1327,7 @@ static int link_send_sections_long(struct port *sender,
                                   u32 destaddr)
 {
        struct link *l_ptr;
-       struct node *node;
+       struct tipc_node *node;
        struct tipc_msg *hdr = &sender->publ.phdr;
        u32 dsz = msg_data_sz(hdr);
        u32 max_pkt,fragm_sz,rest;
@@ -1373,8 +1354,8 @@ again:
        /* Prepare reusable fragment header: */
 
        msg_dbg(hdr, ">FRAGMENTING>");
-       msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT,
-                TIPC_OK, INT_H_SIZE, msg_destnode(hdr));
+       tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT,
+                INT_H_SIZE, msg_destnode(hdr));
        msg_set_link_selector(&fragm_hdr, sender->publ.ref);
        msg_set_size(&fragm_hdr, max_pkt);
        msg_set_fragm_no(&fragm_hdr, 1);
@@ -1464,8 +1445,8 @@ error:
                        tipc_node_unlock(node);
                        goto reject;
                }
-               if (link_max_pkt(l_ptr) < max_pkt) {
-                       sender->publ.max_pkt = link_max_pkt(l_ptr);
+               if (l_ptr->max_pkt < max_pkt) {
+                       sender->publ.max_pkt = l_ptr->max_pkt;
                        tipc_node_unlock(node);
                        for (; buf_chain; buf_chain = buf) {
                                buf = buf_chain->next;
@@ -1535,7 +1516,7 @@ u32 tipc_link_push_packet(struct link *l_ptr)
 
        /* Continue retransmission now, if there is anything: */
 
-       if (r_q_size && buf && !skb_cloned(buf)) {
+       if (r_q_size && buf) {
                msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1));
                msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in);
                if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
@@ -1543,7 +1524,7 @@ u32 tipc_link_push_packet(struct link *l_ptr)
                        l_ptr->retransm_queue_head = mod(++r_q_head);
                        l_ptr->retransm_queue_size = --r_q_size;
                        l_ptr->stats.retransmitted++;
-                       return TIPC_OK;
+                       return 0;
                } else {
                        l_ptr->stats.bearer_congs++;
                        msg_dbg(buf_msg(buf), "|>DEF-RETR>");
@@ -1562,7 +1543,7 @@ u32 tipc_link_push_packet(struct link *l_ptr)
                        l_ptr->unacked_window = 0;
                        buf_discard(buf);
                        l_ptr->proto_msg_queue = NULL;
-                       return TIPC_OK;
+                       return 0;
                } else {
                        msg_dbg(buf_msg(buf), "|>DEF-PROT>");
                        l_ptr->stats.bearer_congs++;
@@ -1586,7 +1567,7 @@ u32 tipc_link_push_packet(struct link *l_ptr)
                                        msg_set_type(msg, CLOSED_MSG);
                                msg_dbg(msg, ">PUSH-DATA>");
                                l_ptr->next_out = buf->next;
-                               return TIPC_OK;
+                               return 0;
                        } else {
                                msg_dbg(msg, "|PUSH-DATA|");
                                l_ptr->stats.bearer_congs++;
@@ -1610,15 +1591,15 @@ void tipc_link_push_queue(struct link *l_ptr)
 
        do {
                res = tipc_link_push_packet(l_ptr);
-       }
-       while (res == TIPC_OK);
+       } while (!res);
+
        if (res == PUSH_FAILED)
                tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
 }
 
 static void link_reset_all(unsigned long addr)
 {
-       struct node *n_ptr;
+       struct tipc_node *n_ptr;
        char addr_string[16];
        u32 i;
 
@@ -1632,7 +1613,7 @@ static void link_reset_all(unsigned long addr)
        tipc_node_lock(n_ptr);
 
        warn("Resetting all links to %s\n",
-            addr_string_fill(addr_string, n_ptr->addr));
+            tipc_addr_string_fill(addr_string, n_ptr->addr));
 
        for (i = 0; i < MAX_BEARERS; i++) {
                if (n_ptr->links[i]) {
@@ -1651,7 +1632,7 @@ static void link_retransmit_failure(struct link *l_ptr, struct sk_buff *buf)
        struct tipc_msg *msg = buf_msg(buf);
 
        warn("Retransmission failure on link <%s>\n", l_ptr->name);
-       tipc_msg_print(TIPC_OUTPUT, msg, ">RETR-FAIL>");
+       tipc_msg_dbg(TIPC_OUTPUT, msg, ">RETR-FAIL>");
 
        if (l_ptr->addr) {
 
@@ -1664,7 +1645,7 @@ static void link_retransmit_failure(struct link *l_ptr, struct sk_buff *buf)
 
                /* Handle failure on broadcast link */
 
-               struct node *n_ptr;
+               struct tipc_node *n_ptr;
                char addr_string[16];
 
                tipc_printf(TIPC_OUTPUT, "Msg seq number: %u,  ", msg_seqno(msg));
@@ -1674,7 +1655,7 @@ static void link_retransmit_failure(struct link *l_ptr, struct sk_buff *buf)
                n_ptr = l_ptr->owner->next;
                tipc_node_lock(n_ptr);
 
-               addr_string_fill(addr_string, n_ptr->addr);
+               tipc_addr_string_fill(addr_string, n_ptr->addr);
                tipc_printf(TIPC_OUTPUT, "Multicast link info for %s\n", addr_string);
                tipc_printf(TIPC_OUTPUT, "Supported: %d,  ", n_ptr->bclink.supported);
                tipc_printf(TIPC_OUTPUT, "Acked: %u\n", n_ptr->bclink.acked);
@@ -1704,15 +1685,16 @@ void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf,
        dbg("Retransmitting %u in link %x\n", retransmits, l_ptr);
 
        if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) {
-               if (!skb_cloned(buf)) {
+               if (l_ptr->retransm_queue_size == 0) {
                        msg_dbg(msg, ">NO_RETR->BCONG>");
                        dbg_print_link(l_ptr, "   ");
                        l_ptr->retransm_queue_head = msg_seqno(msg);
                        l_ptr->retransm_queue_size = retransmits;
-                       return;
                } else {
-                       /* Don't retransmit if driver already has the buffer */
+                       err("Unexpected retransmit on link %s (qsize=%d)\n",
+                           l_ptr->name, l_ptr->retransm_queue_size);
                }
+               return;
        } else {
                /* Detect repeated retransmit failures on uncongested bearer */
 
@@ -1727,7 +1709,7 @@ void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf,
                }
        }
 
-       while (retransmits && (buf != l_ptr->next_out) && buf && !skb_cloned(buf)) {
+       while (retransmits && (buf != l_ptr->next_out) && buf) {
                msg = buf_msg(buf);
                msg_set_ack(msg, mod(l_ptr->next_in_no - 1));
                msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
@@ -1748,21 +1730,6 @@ void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf,
        l_ptr->retransm_queue_head = l_ptr->retransm_queue_size = 0;
 }
 
-/*
- * link_recv_non_seq: Receive packets which are outside
- *                    the link sequence flow
- */
-
-static void link_recv_non_seq(struct sk_buff *buf)
-{
-       struct tipc_msg *msg = buf_msg(buf);
-
-       if (msg_user(msg) ==  LINK_CONFIG)
-               tipc_disc_recv_msg(buf);
-       else
-               tipc_bclink_recv_pkt(buf);
-}
-
 /**
  * link_insert_deferred_queue - insert deferred messages back into receive chain
  */
@@ -1785,34 +1752,93 @@ static struct sk_buff *link_insert_deferred_queue(struct link *l_ptr,
        return buf;
 }
 
+/**
+ * link_recv_buf_validate - validate basic format of received message
+ *
+ * This routine ensures a TIPC message has an acceptable header, and at least
+ * as much data as the header indicates it should.  The routine also ensures
+ * that the entire message header is stored in the main fragment of the message
+ * buffer, to simplify future access to message header fields.
+ *
+ * Note: Having extra info present in the message header or data areas is OK.
+ * TIPC will ignore the excess, under the assumption that it is optional info
+ * introduced by a later release of the protocol.
+ */
+
+static int link_recv_buf_validate(struct sk_buff *buf)
+{
+       static u32 min_data_hdr_size[8] = {
+               SHORT_H_SIZE, MCAST_H_SIZE, LONG_H_SIZE, DIR_MSG_H_SIZE,
+               MAX_H_SIZE, MAX_H_SIZE, MAX_H_SIZE, MAX_H_SIZE
+               };
+
+       struct tipc_msg *msg;
+       u32 tipc_hdr[2];
+       u32 size;
+       u32 hdr_size;
+       u32 min_hdr_size;
+
+       if (unlikely(buf->len < MIN_H_SIZE))
+               return 0;
+
+       msg = skb_header_pointer(buf, 0, sizeof(tipc_hdr), tipc_hdr);
+       if (msg == NULL)
+               return 0;
+
+       if (unlikely(msg_version(msg) != TIPC_VERSION))
+               return 0;
+
+       size = msg_size(msg);
+       hdr_size = msg_hdr_sz(msg);
+       min_hdr_size = msg_isdata(msg) ?
+               min_data_hdr_size[msg_type(msg)] : INT_H_SIZE;
+
+       if (unlikely((hdr_size < min_hdr_size) ||
+                    (size < hdr_size) ||
+                    (buf->len < size) ||
+                    (size - hdr_size > TIPC_MAX_USER_MSG_SIZE)))
+               return 0;
+
+       return pskb_may_pull(buf, hdr_size);
+}
+
 void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
 {
        read_lock_bh(&tipc_net_lock);
        while (head) {
-               struct bearer *b_ptr;
-               struct node *n_ptr;
+               struct bearer *b_ptr = (struct bearer *)tb_ptr;
+               struct tipc_node *n_ptr;
                struct link *l_ptr;
                struct sk_buff *crs;
                struct sk_buff *buf = head;
-               struct tipc_msg *msg = buf_msg(buf);
-               u32 seq_no = msg_seqno(msg);
-               u32 ackd = msg_ack(msg);
+               struct tipc_msg *msg;
+               u32 seq_no;
+               u32 ackd;
                u32 released = 0;
                int type;
 
-               b_ptr = (struct bearer *)tb_ptr;
-               TIPC_SKB_CB(buf)->handle = b_ptr;
-
                head = head->next;
-               if (unlikely(msg_version(msg) != TIPC_VERSION))
+
+               /* Ensure message is well-formed */
+
+               if (unlikely(!link_recv_buf_validate(buf)))
                        goto cont;
-#if 0
-               if (msg_user(msg) != LINK_PROTOCOL)
-#endif
-                       msg_dbg(msg,"<REC<");
+
+               /* Ensure message data is a single contiguous unit */
+
+               if (unlikely(buf_linearize(buf))) {
+                       goto cont;
+               }
+
+               /* Handle arrival of a non-unicast link message */
+
+               msg = buf_msg(buf);
 
                if (unlikely(msg_non_seq(msg))) {
-                       link_recv_non_seq(buf);
+                       if (msg_user(msg) ==  LINK_CONFIG)
+                               tipc_disc_recv_msg(buf, b_ptr);
+                       else
+                               tipc_bclink_recv_pkt(buf);
                        continue;
                }
 
@@ -1820,19 +1846,35 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
                             (msg_destnode(msg) != tipc_own_addr)))
                        goto cont;
 
+               /* Discard non-routeable messages destined for another node */
+
+               if (unlikely(!msg_isdata(msg) &&
+                            (msg_destnode(msg) != tipc_own_addr))) {
+                       if ((msg_user(msg) != CONN_MANAGER) &&
+                           (msg_user(msg) != MSG_FRAGMENTER))
+                               goto cont;
+               }
+
+               /* Locate unicast link endpoint that should handle message */
+
                n_ptr = tipc_node_find(msg_prevnode(msg));
                if (unlikely(!n_ptr))
                        goto cont;
-
                tipc_node_lock(n_ptr);
+
                l_ptr = n_ptr->links[b_ptr->identity];
                if (unlikely(!l_ptr)) {
                        tipc_node_unlock(n_ptr);
                        goto cont;
                }
-               /*
-                * Release acked messages
-                */
+
+               /* Validate message sequence number info */
+
+               seq_no = msg_seqno(msg);
+               ackd = msg_ack(msg);
+
+               /* Release acked messages */
+
                if (less(n_ptr->bclink.acked, msg_bcast_ack(msg))) {
                        if (tipc_node_is_up(n_ptr) && n_ptr->bclink.supported)
                                tipc_bclink_acknowledge(n_ptr, msg_bcast_ack(msg));
@@ -1851,6 +1893,9 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
                        l_ptr->first_out = crs;
                        l_ptr->out_queue_size -= released;
                }
+
+               /* Try sending any messages link endpoint has pending */
+
                if (unlikely(l_ptr->next_out))
                        tipc_link_push_queue(l_ptr);
                if (unlikely(!list_empty(&l_ptr->waiting_ports)))
@@ -1860,6 +1905,8 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
                        tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0);
                }
 
+               /* Now (finally!) process the incoming message */
+
 protocol_check:
                if (likely(link_working_working(l_ptr))) {
                        if (likely(seq_no == mod(l_ptr->next_in_no))) {
@@ -1907,8 +1954,6 @@ deliver:
                                                if (link_recv_changeover_msg(&l_ptr, &buf)) {
                                                        msg = buf_msg(buf);
                                                        seq_no = msg_seqno(msg);
-                                                       TIPC_SKB_CB(buf)->handle
-                                                               = b_ptr;
                                                        if (type == ORIGINAL_MSG)
                                                                goto deliver;
                                                        goto protocol_check;
@@ -2192,7 +2237,8 @@ static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf)
        switch (msg_type(msg)) {
 
        case RESET_MSG:
-               if (!link_working_unknown(l_ptr) && l_ptr->peer_session) {
+               if (!link_working_unknown(l_ptr) &&
+                   (l_ptr->peer_session != INVALID_SESSION)) {
                        if (msg_session(msg) == l_ptr->peer_session) {
                                dbg("Duplicate RESET: %u<->%u\n",
                                    msg_session(msg), l_ptr->peer_session);
@@ -2352,8 +2398,8 @@ void tipc_link_changeover(struct link *l_ptr)
                return;
        }
 
-       msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL,
-                ORIGINAL_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr);
+       tipc_msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL,
+                ORIGINAL_MSG, INT_H_SIZE, l_ptr->addr);
        msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id);
        msg_set_msgcnt(&tunnel_hdr, msgcount);
        dbg("Link changeover requires %u tunnel messages\n", msgcount);
@@ -2407,8 +2453,8 @@ void tipc_link_send_duplicate(struct link *l_ptr, struct link *tunnel)
        struct sk_buff *iter;
        struct tipc_msg tunnel_hdr;
 
-       msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL,
-                DUPLICATE_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr);
+       tipc_msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL,
+                DUPLICATE_MSG, INT_H_SIZE, l_ptr->addr);
        msg_set_msgcnt(&tunnel_hdr, l_ptr->out_queue_size);
        msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id);
        iter = l_ptr->first_out;
@@ -2598,21 +2644,23 @@ int tipc_link_send_long_buf(struct link *l_ptr, struct sk_buff *buf)
        u32 dsz = msg_data_sz(inmsg);
        unchar *crs = buf->data;
        u32 rest = insize;
-       u32 pack_sz = link_max_pkt(l_ptr);
+       u32 pack_sz = l_ptr->max_pkt;
        u32 fragm_sz = pack_sz - INT_H_SIZE;
        u32 fragm_no = 1;
-       u32 destaddr = msg_destnode(inmsg);
+       u32 destaddr;
 
        if (msg_short(inmsg))
                destaddr = l_ptr->addr;
+       else
+               destaddr = msg_destnode(inmsg);
 
        if (msg_routed(inmsg))
                msg_set_prevnode(inmsg, tipc_own_addr);
 
        /* Prepare reusable fragment header: */
 
-       msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT,
-                TIPC_OK, INT_H_SIZE, destaddr);
+       tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT,
+                INT_H_SIZE, destaddr);
        msg_set_link_selector(&fragm_hdr, msg_link_selector(inmsg));
        msg_set_long_msgno(&fragm_hdr, mod(l_ptr->long_msg_seq_no++));
        msg_set_fragm_no(&fragm_hdr, fragm_no);
@@ -2713,8 +2761,8 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb,
 
        /* Is there an incomplete message waiting for this fragment? */
 
-       while (pbuf && ((msg_seqno(buf_msg(pbuf)) != long_msg_seq_no)
-                       || (msg_orignode(fragm) != msg_orignode(buf_msg(pbuf))))) {
+       while (pbuf && ((msg_seqno(buf_msg(pbuf)) != long_msg_seq_no) ||
+                       (msg_orignode(fragm) != msg_orignode(buf_msg(pbuf))))) {
                prev = pbuf;
                pbuf = pbuf->next;
        }
@@ -2832,15 +2880,15 @@ static void link_set_supervision_props(struct link *l_ptr, u32 tolerance)
 void tipc_link_set_queue_limits(struct link *l_ptr, u32 window)
 {
        /* Data messages from this node, inclusive FIRST_FRAGM */
-       l_ptr->queue_limit[DATA_LOW] = window;
-       l_ptr->queue_limit[DATA_MEDIUM] = (window / 3) * 4;
-       l_ptr->queue_limit[DATA_HIGH] = (window / 3) * 5;
-       l_ptr->queue_limit[DATA_CRITICAL] = (window / 3) * 6;
+       l_ptr->queue_limit[TIPC_LOW_IMPORTANCE] = window;
+       l_ptr->queue_limit[TIPC_MEDIUM_IMPORTANCE] = (window / 3) * 4;
+       l_ptr->queue_limit[TIPC_HIGH_IMPORTANCE] = (window / 3) * 5;
+       l_ptr->queue_limit[TIPC_CRITICAL_IMPORTANCE] = (window / 3) * 6;
        /* Transiting data messages,inclusive FIRST_FRAGM */
-       l_ptr->queue_limit[DATA_LOW + 4] = 300;
-       l_ptr->queue_limit[DATA_MEDIUM + 4] = 600;
-       l_ptr->queue_limit[DATA_HIGH + 4] = 900;
-       l_ptr->queue_limit[DATA_CRITICAL + 4] = 1200;
+       l_ptr->queue_limit[TIPC_LOW_IMPORTANCE + 4] = 300;
+       l_ptr->queue_limit[TIPC_MEDIUM_IMPORTANCE + 4] = 600;
+       l_ptr->queue_limit[TIPC_HIGH_IMPORTANCE + 4] = 900;
+       l_ptr->queue_limit[TIPC_CRITICAL_IMPORTANCE + 4] = 1200;
        l_ptr->queue_limit[CONN_MANAGER] = 1200;
        l_ptr->queue_limit[ROUTE_DISTRIBUTOR] = 1200;
        l_ptr->queue_limit[CHANGEOVER_PROTOCOL] = 2500;
@@ -2860,7 +2908,7 @@ void tipc_link_set_queue_limits(struct link *l_ptr, u32 window)
  * Returns pointer to link (or 0 if invalid link name).
  */
 
-static struct link *link_find_link(const char *name, struct node **node)
+static struct link *link_find_link(const char *name, struct tipc_node **node)
 {
        struct link_name link_name_parts;
        struct bearer *b_ptr;
@@ -2890,7 +2938,7 @@ struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space
        struct tipc_link_config *args;
        u32 new_value;
        struct link *l_ptr;
-       struct node *node;
+       struct tipc_node *node;
        int res;
 
        if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_CONFIG))
@@ -2923,7 +2971,7 @@ struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space
                        link_set_supervision_props(l_ptr, new_value);
                        tipc_link_send_proto_msg(l_ptr, STATE_MSG,
                                                 0, 0, new_value, 0, 0);
-                       res = TIPC_OK;
+                       res = 0;
                }
                break;
        case TIPC_CMD_SET_LINK_PRI:
@@ -2932,14 +2980,14 @@ struct sk_buff *tipc_link_cmd_config(const void *req_tlv_area, int req_tlv_space
                        l_ptr->priority = new_value;
                        tipc_link_send_proto_msg(l_ptr, STATE_MSG,
                                                 0, 0, 0, new_value, 0);
-                       res = TIPC_OK;
+                       res = 0;
                }
                break;
        case TIPC_CMD_SET_LINK_WINDOW:
                if ((new_value >= TIPC_MIN_LINK_WIN) &&
                    (new_value <= TIPC_MAX_LINK_WIN)) {
                        tipc_link_set_queue_limits(l_ptr, new_value);
-                       res = TIPC_OK;
+                       res = 0;
                }
                break;
        }
@@ -2968,7 +3016,7 @@ struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_
 {
        char *link_name;
        struct link *l_ptr;
-       struct node *node;
+       struct tipc_node *node;
 
        if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME))
                return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
@@ -3016,7 +3064,7 @@ static int tipc_link_stats(const char *name, char *buf, const u32 buf_size)
 {
        struct print_buf pb;
        struct link *l_ptr;
-       struct node *node;
+       struct tipc_node *node;
        char *status;
        u32 profile_total = 0;
 
@@ -3042,7 +3090,7 @@ static int tipc_link_stats(const char *name, char *buf, const u32 buf_size)
        tipc_printf(&pb, "Link <%s>\n"
                         "  %s  MTU:%u  Priority:%u  Tolerance:%u ms"
                         "  Window:%u packets\n",
-                   l_ptr->name, status, link_max_pkt(l_ptr),
+                   l_ptr->name, status, l_ptr->max_pkt,
                    l_ptr->priority, l_ptr->tolerance, l_ptr->queue_limit[0]);
        tipc_printf(&pb, "  RX packets:%u fragments:%u/%u bundles:%u/%u\n",
                    l_ptr->next_in_no - l_ptr->stats.recv_info,
@@ -3132,7 +3180,7 @@ int link_control(const char *name, u32 op, u32 val)
        int res = -EINVAL;
        struct link *l_ptr;
        u32 bearer_id;
-       struct node * node;
+       struct tipc_node * node;
        u32 a;
 
        a = link_name2addr(name, &bearer_id);
@@ -3155,7 +3203,7 @@ int link_control(const char *name, u32 op, u32 val)
                        if (op == TIPC_CMD_UNBLOCK_LINK) {
                                l_ptr->blocked = 0;
                        }
-                       res = TIPC_OK;
+                       res = 0;
                }
                tipc_node_unlock(node);
        }
@@ -3174,7 +3222,7 @@ int link_control(const char *name, u32 op, u32 val)
 
 u32 tipc_link_get_max_pkt(u32 dest, u32 selector)
 {
-       struct node *n_ptr;
+       struct tipc_node *n_ptr;
        struct link *l_ptr;
        u32 res = MAX_PKT_DEFAULT;
 
@@ -3187,7 +3235,7 @@ u32 tipc_link_get_max_pkt(u32 dest, u32 selector)
                tipc_node_lock(n_ptr);
                l_ptr = n_ptr->active_links[selector & 1];
                if (l_ptr)
-                       res = link_max_pkt(l_ptr);
+                       res = l_ptr->max_pkt;
                tipc_node_unlock(n_ptr);
        }
        read_unlock_bh(&tipc_net_lock);
@@ -3210,7 +3258,7 @@ static void link_dump_rec_queue(struct link *l_ptr)
                        info("buffer %x invalid\n", crs);
                        return;
                }
-               msg_dbg(buf_msg(crs), "In rec queue: \n");
+               msg_dbg(buf_msg(crs), "In rec queue:\n");
                crs = crs->next;
        }
 }
@@ -3245,13 +3293,11 @@ static void link_print(struct link *l_ptr, struct print_buf *buf,
                if (l_ptr->next_out)
                        tipc_printf(buf, "%u..",
                                    msg_seqno(buf_msg(l_ptr->next_out)));
-               tipc_printf(buf, "%u]",
-                           msg_seqno(buf_msg
-                                     (l_ptr->last_out)), l_ptr->out_queue_size);
+               tipc_printf(buf, "%u]", msg_seqno(buf_msg(l_ptr->last_out)));
                if ((mod(msg_seqno(buf_msg(l_ptr->last_out)) -
                         msg_seqno(buf_msg(l_ptr->first_out)))
-                    != (l_ptr->out_queue_size - 1))
-                   || (l_ptr->last_out->next != 0)) {
+                    != (l_ptr->out_queue_size - 1)) ||
+                   (l_ptr->last_out->next != NULL)) {
                        tipc_printf(buf, "\nSend queue inconsistency\n");
                        tipc_printf(buf, "first_out= %x ", l_ptr->first_out);
                        tipc_printf(buf, "next_out= %x ", l_ptr->next_out);