Index: uspace/srv/net/tl/tcp/ucall.c
===================================================================
--- uspace/srv/net/tl/tcp/ucall.c	(revision 7a8c1c4e5b8ffa09d9d43a81d222f21253b15586)
+++ uspace/srv/net/tl/tcp/ucall.c	(revision 153cc76acfecd18d9bb208e102fdfe6aa9926b08)
@@ -83,9 +83,9 @@
 	/* Wait for connection to be established or reset */
 	log_msg(LVL_DEBUG, "tcp_uc_open: Wait for connection.");
-	fibril_mutex_lock(&nconn->cstate_lock);
+	fibril_mutex_lock(&nconn->lock);
 	while (nconn->cstate == st_listen ||
 	    nconn->cstate == st_syn_sent ||
 	    nconn->cstate == st_syn_received) {
-		fibril_condvar_wait(&nconn->cstate_cv, &nconn->cstate_lock);
+		fibril_condvar_wait(&nconn->cstate_cv, &nconn->lock);
 	}
 
@@ -93,9 +93,9 @@
 		log_msg(LVL_DEBUG, "tcp_uc_open: Connection was reset.");
 		assert(nconn->cstate == st_closed);
-		fibril_mutex_unlock(&nconn->cstate_lock);
+		fibril_mutex_unlock(&nconn->lock);
 		return TCP_ERESET;
 	}
 
-	fibril_mutex_unlock(&nconn->cstate_lock);
+	fibril_mutex_unlock(&nconn->lock);
 	log_msg(LVL_DEBUG, "tcp_uc_open: Connection was established.");
 
@@ -113,6 +113,10 @@
 	log_msg(LVL_DEBUG, "%s: tcp_uc_send()", conn->name);
 
-	if (conn->cstate == st_closed)
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		fibril_mutex_unlock(&conn->lock);
 		return TCP_ENOTEXIST;
+	}
 
 	if (conn->cstate == st_listen) {
@@ -121,8 +125,7 @@
 	}
 
-	fibril_mutex_lock(&conn->snd_buf_lock);
 
 	if (conn->snd_buf_fin) {
-		fibril_mutex_unlock(&conn->snd_buf_lock);
+		fibril_mutex_unlock(&conn->lock);
 		return TCP_ECLOSING;
 	}
@@ -133,11 +136,10 @@
 			log_msg(LVL_DEBUG, "%s: buf_free == 0, waiting.",
 			    conn->name);
-			fibril_condvar_wait(&conn->snd_buf_cv,
-			    &conn->snd_buf_lock);
+			fibril_condvar_wait(&conn->snd_buf_cv, &conn->lock);
 			buf_free = conn->snd_buf_size - conn->snd_buf_used;
 		}
 
 		if (conn->reset) {
-			fibril_mutex_unlock(&conn->snd_buf_lock);
+			fibril_mutex_unlock(&conn->lock);
 			return TCP_ERESET;
 		}
@@ -151,11 +153,9 @@
 		size -= xfer_size;
 
-		fibril_mutex_unlock(&conn->snd_buf_lock);
 		tcp_tqueue_new_data(conn);
-		fibril_mutex_lock(&conn->snd_buf_lock);
-	}
-
-	fibril_mutex_unlock(&conn->snd_buf_lock);
+	}
+
 	tcp_tqueue_new_data(conn);
+	fibril_mutex_unlock(&conn->lock);
 
 	return TCP_EOK;
@@ -170,18 +170,18 @@
 	log_msg(LVL_DEBUG, "%s: tcp_uc_receive()", conn->name);
 
-	if (conn->cstate == st_closed)
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		fibril_mutex_unlock(&conn->lock);
 		return TCP_ENOTEXIST;
-
-	fibril_mutex_lock(&conn->rcv_buf_lock);
+	}
 
 	/* Wait for data to become available */
 	while (conn->rcv_buf_used == 0 && !conn->rcv_buf_fin && !conn->reset) {
 		log_msg(LVL_DEBUG, "tcp_uc_receive() - wait for data");
-		fibril_condvar_wait(&conn->rcv_buf_cv, &conn->rcv_buf_lock);
+		fibril_condvar_wait(&conn->rcv_buf_cv, &conn->lock);
 	}
 
 	if (conn->rcv_buf_used == 0) {
-		fibril_mutex_unlock(&conn->rcv_buf_lock);
-
 		*rcvd = 0;
 		*xflags = 0;
@@ -189,8 +189,10 @@
 		if (conn->rcv_buf_fin) {
 			/* End of data, peer closed connection */
+			fibril_mutex_unlock(&conn->lock);
 			return TCP_ECLOSING;
 		} else {
 			/* Connection was reset */
 			assert(conn->reset);
+			fibril_mutex_unlock(&conn->lock);
 			return TCP_ERESET;
 		}
@@ -208,6 +210,4 @@
 	conn->rcv_wnd += xfer_size;
 
-	fibril_mutex_unlock(&conn->rcv_buf_lock);
-
 	/* TODO */
 	*xflags = 0;
@@ -219,4 +219,6 @@
 	    conn->name, xfer_size);
 
+	fibril_mutex_unlock(&conn->lock);
+
 	return TCP_EOK;
 }
@@ -227,13 +229,20 @@
 	log_msg(LVL_DEBUG, "%s: tcp_uc_close()", conn->name);
 
-	if (conn->cstate == st_closed)
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		fibril_mutex_unlock(&conn->lock);
 		return TCP_ENOTEXIST;
-
-	if (conn->snd_buf_fin)
+	}
+
+	if (conn->snd_buf_fin) {
+		fibril_mutex_unlock(&conn->lock);
 		return TCP_ECLOSING;
+	}
 
 	conn->snd_buf_fin = true;
 	tcp_tqueue_new_data(conn);
 
+	fibril_mutex_unlock(&conn->lock);
 	return TCP_EOK;
 }
@@ -276,21 +285,32 @@
 	    sp->local.addr.ipv4, sp->local.port);
 
-	conn = tcp_conn_find(sp);
-	if (conn != NULL && conn->cstate != st_closed) {
-		if (conn->ident.foreign.addr.ipv4 == TCP_IPV4_ANY)
-			conn->ident.foreign.addr.ipv4 = sp->foreign.addr.ipv4;
-		if (conn->ident.foreign.port == TCP_PORT_ANY)
-			conn->ident.foreign.port = sp->foreign.port;
-		if (conn->ident.local.addr.ipv4 == TCP_IPV4_ANY)
-			conn->ident.local.addr.ipv4 = sp->local.addr.ipv4;
-
-		tcp_conn_segment_arrived(conn, seg);
-	} else {
-		if (conn == NULL)
-			log_msg(LVL_WARN, "No connection found.");
-		else
-			log_msg(LVL_WARN, "Connection is closed.");
+	conn = tcp_conn_find_ref(sp);
+	if (conn == NULL) {
+		log_msg(LVL_WARN, "No connection found.");
 		tcp_unexpected_segment(sp, seg);
-	}
+		return;
+	}
+
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		log_msg(LVL_WARN, "Connection is closed.");
+		tcp_unexpected_segment(sp, seg);
+		fibril_mutex_unlock(&conn->lock);
+		tcp_conn_delref(conn);
+		return;
+	}
+
+	if (conn->ident.foreign.addr.ipv4 == TCP_IPV4_ANY)
+		conn->ident.foreign.addr.ipv4 = sp->foreign.addr.ipv4;
+	if (conn->ident.foreign.port == TCP_PORT_ANY)
+		conn->ident.foreign.port = sp->foreign.port;
+	if (conn->ident.local.addr.ipv4 == TCP_IPV4_ANY)
+		conn->ident.local.addr.ipv4 = sp->local.addr.ipv4;
+
+	tcp_conn_segment_arrived(conn, seg);
+
+	fibril_mutex_unlock(&conn->lock);
+	tcp_conn_delref(conn);
 }
 
