[TIPC]: Overhaul of socket locking logic

This patch modifies TIPC's socket code to follow the same approach
used by other protocols.  This change eliminates the need for a
mutex in the TIPC-specific portion of the socket protocol data
structure -- in its place, the standard Linux socket backlog queue
and associated locking routines are utilized.  These changes fix
a long-standing receive queue bug on SMP systems, and also enable
individual read and write threads to utilize a socket without
unnecessarily interfering with each other.

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/net/tipc/port.c b/net/tipc/port.c
index e2646a9..2f58064 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -1240,6 +1240,28 @@
 	return res;
 }
 
+/**
+ * tipc_disconnect_port - disconnect port from peer
+ *
+ * Port must be locked.
+ */
+
+int tipc_disconnect_port(struct tipc_port *tp_ptr)
+{
+	int res;
+
+	if (tp_ptr->connected) {
+		tp_ptr->connected = 0;
+		/* let timer expire on it's own to avoid deadlock! */
+		tipc_nodesub_unsubscribe(
+			&((struct port *)tp_ptr)->subscription);
+		res = TIPC_OK;
+	} else {
+		res = -ENOTCONN;
+	}
+	return res;
+}
+
 /*
  * tipc_disconnect(): Disconnect port form peer.
  *                    This is a node local operation.
@@ -1248,17 +1270,12 @@
 int tipc_disconnect(u32 ref)
 {
 	struct port *p_ptr;
-	int res = -ENOTCONN;
+	int res;
 
 	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
-	if (p_ptr->publ.connected) {
-		p_ptr->publ.connected = 0;
-		/* let timer expire on it's own to avoid deadlock! */
-		tipc_nodesub_unsubscribe(&p_ptr->subscription);
-		res = TIPC_OK;
-	}
+	res = tipc_disconnect_port((struct tipc_port *)p_ptr);
 	tipc_port_unlock(p_ptr);
 	return res;
 }