Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 422af2b1e7236addac60aba765ad4a3d606b1365)
+++ uspace/Makefile	(revision 68f57e1baf7a0ef1d2d7ca7bc3648755a58dcc03)
@@ -51,4 +51,5 @@
 	app/mkexfat \
 	app/mkmfs \
+	app/nterm \
 	app/redir \
 	app/sbi \
Index: uspace/app/nterm/Makefile
===================================================================
--- uspace/app/nterm/Makefile	(revision 68f57e1baf7a0ef1d2d7ca7bc3648755a58dcc03)
+++ uspace/app/nterm/Makefile	(revision 68f57e1baf7a0ef1d2d7ca7bc3648755a58dcc03)
@@ -0,0 +1,36 @@
+#
+# Copyright (c) 2012 Jiri Svoboda
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../..
+BINARY = nterm
+
+SOURCES = \
+	conn.c \
+	nterm.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/app/nterm/conn.c
===================================================================
--- uspace/app/nterm/conn.c	(revision 68f57e1baf7a0ef1d2d7ca7bc3648755a58dcc03)
+++ uspace/app/nterm/conn.c	(revision 68f57e1baf7a0ef1d2d7ca7bc3648755a58dcc03)
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup nterm
+ * @{
+ */
+/** @file
+ */
+
+#include <bool.h>
+#include <errno.h>
+#include <fibril.h>
+#include <net/socket.h>
+#include <stdio.h>
+#include <str_error.h>
+#include <sys/types.h>
+
+#include "conn.h"
+#include "nterm.h"
+
+static int conn_fd;
+static fid_t rcv_fid;
+
+#define RECV_BUF_SIZE 1024
+static uint8_t recv_buf[RECV_BUF_SIZE];
+
+static int rcv_fibril(void *arg)
+{
+	ssize_t nr;
+
+	while (true) {
+		nr = recv(conn_fd, recv_buf, RECV_BUF_SIZE, 0);
+		if (nr < 0)
+			break;
+
+		nterm_received(recv_buf, nr);
+	}
+
+	if (nr == ENOTCONN)
+		printf("\n[Other side has closed the connection]\n");
+	else
+		printf("'\n[Receive errror (%s)]\n", str_error(nr));
+
+	exit(0);
+	return 0;
+}
+
+int conn_open(const char *addr_s, const char *port_s)
+{
+	struct sockaddr_in addr;
+	int rc;
+	char *endptr;
+
+	addr.sin_family = AF_INET;
+
+	rc = inet_pton(addr.sin_family, addr_s, (uint8_t *)&addr.sin_addr);
+	if (rc != EOK) {
+		printf("Invalid addres %s\n", addr_s);
+		return EINVAL;
+	}
+
+	addr.sin_port = htons(strtol(port_s, &endptr, 10));
+	if (*endptr != '\0') {
+		printf("Invalid port number %s\n", port_s);
+		return EINVAL;
+	}
+
+	conn_fd = socket(PF_INET, SOCK_STREAM, 0);
+	if (conn_fd < 0)
+		goto error;
+
+	printf("Connecting to address %s port %u\n", addr_s, ntohs(addr.sin_port));
+
+	rc = connect(conn_fd, (struct sockaddr *)&addr, sizeof(addr));
+	if (rc != EOK)
+		goto error;
+
+	rcv_fid = fibril_create(rcv_fibril, NULL);
+	if (rcv_fid == 0)
+		goto error;
+
+	fibril_add_ready(rcv_fid);
+
+	return EOK;
+
+error:
+	if (conn_fd >= 0) {
+		closesocket(conn_fd);
+		conn_fd = -1;
+	}
+
+	return EIO;
+}
+
+int conn_send(void *data, size_t size)
+{
+	int rc;
+
+	rc = send(conn_fd, data, size, 0);
+	if (rc != EOK)
+		return EIO;
+
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/app/nterm/conn.h
===================================================================
--- uspace/app/nterm/conn.h	(revision 68f57e1baf7a0ef1d2d7ca7bc3648755a58dcc03)
+++ uspace/app/nterm/conn.h	(revision 68f57e1baf7a0ef1d2d7ca7bc3648755a58dcc03)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup edit
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef CONN_H
+#define CONN_H
+
+#include <sys/types.h>
+
+extern int conn_open(const char *, const char *);
+extern int conn_send(void *, size_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/app/nterm/nterm.c
===================================================================
--- uspace/app/nterm/nterm.c	(revision 68f57e1baf7a0ef1d2d7ca7bc3648755a58dcc03)
+++ uspace/app/nterm/nterm.c	(revision 68f57e1baf7a0ef1d2d7ca7bc3648755a58dcc03)
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup nterm
+ * @{
+ */
+/** @file Network serial terminal emulator.
+ */
+
+#include <bool.h>
+#include <errno.h>
+#include <io/console.h>
+#include <stdio.h>
+
+#include "conn.h"
+#include "nterm.h"
+
+#define NAME "nterm"
+
+static console_ctrl_t *con;
+static bool done;
+
+static void key_handle_ctrl(kbd_event_t *ev)
+{
+	switch (ev->key) {
+	case KC_Q:
+		done = true;
+		break;
+	default:
+		break;
+	}
+}
+
+static void send_char(wchar_t c)
+{
+	char cbuf[STR_BOUNDS(1)];
+	size_t offs;
+	int rc;
+
+	offs = 0;
+	chr_encode(c, cbuf, &offs, STR_BOUNDS(1));
+
+	rc = conn_send(cbuf, offs);
+	if (rc != EOK) {
+		printf("[Failed sending data]\n");
+	}
+}
+
+static void key_handle_unmod(kbd_event_t *ev)
+{
+	switch (ev->key) {
+	case KC_ENTER:
+		send_char('\n');
+		break;
+	default:
+		if (ev->c >= 32 || ev->c == '\t' || ev->c == '\b') {
+			send_char(ev->c);
+		}
+	}
+}
+
+static void key_handle(kbd_event_t *ev)
+{
+	if ((ev->mods & KM_ALT) == 0 &&
+	    (ev->mods & KM_SHIFT) == 0 &&
+	    (ev->mods & KM_CTRL) != 0) {
+		key_handle_ctrl(ev);
+	} else if ((ev->mods & (KM_CTRL | KM_ALT)) == 0) {
+		key_handle_unmod(ev);
+	}
+}
+
+void nterm_received(void *data, size_t size)
+{
+	fwrite(data, size, 1, stdout);
+	fflush(stdout);
+}
+
+static void print_syntax(void)
+{
+	printf("syntax: nterm <ip-address> <port>\n");
+}
+
+int main(int argc, char *argv[])
+{
+	kbd_event_t ev;
+	int rc;
+
+	if (argc != 3) {
+		print_syntax();
+		return 1;
+	}
+
+	rc = conn_open(argv[1], argv[2]);
+	if (rc != EOK) {
+		printf("Error connecting.\n");
+		return 1;
+	}
+
+	printf("Connection established.\n");
+
+	con = console_init(stdin, stdout);
+
+	done = false;
+	while (!done) {
+		console_get_kbd_event(con, &ev);
+		if (ev.type == KEY_PRESS)
+			key_handle(&ev);
+	}
+
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/app/nterm/nterm.h
===================================================================
--- uspace/app/nterm/nterm.h	(revision 68f57e1baf7a0ef1d2d7ca7bc3648755a58dcc03)
+++ uspace/app/nterm/nterm.h	(revision 68f57e1baf7a0ef1d2d7ca7bc3648755a58dcc03)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup edit
+ * @{
+ */
+/**
+ * @file
+ */
+
+#ifndef NTERM_H
+#define NTERM_H
+
+#include <sys/types.h>
+
+extern void nterm_received(void *, size_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/usb/include/usb/debug.h
===================================================================
--- uspace/lib/usb/include/usb/debug.h	(revision 422af2b1e7236addac60aba765ad4a3d606b1365)
+++ uspace/lib/usb/include/usb/debug.h	(revision 68f57e1baf7a0ef1d2d7ca7bc3648755a58dcc03)
@@ -81,8 +81,8 @@
 
 /** Default log level. */
-#ifdef CONFIG_USB_RELEASE_BUILD
+#ifdef CONFIG_USB_VERBOSE
+#  define USB_LOG_LEVEL_DEFAULT USB_LOG_LEVEL_DEBUG
+#else
 #  define USB_LOG_LEVEL_DEFAULT USB_LOG_LEVEL_INFO
-#else
-#  define USB_LOG_LEVEL_DEFAULT USB_LOG_LEVEL_DEBUG
 #endif
 
Index: uspace/srv/net/tcp/conn.c
===================================================================
--- uspace/srv/net/tcp/conn.c	(revision 422af2b1e7236addac60aba765ad4a3d606b1365)
+++ uspace/srv/net/tcp/conn.c	(revision 68f57e1baf7a0ef1d2d7ca7bc3648755a58dcc03)
@@ -184,5 +184,5 @@
 void tcp_conn_addref(tcp_conn_t *conn)
 {
-	log_msg(LVL_DEBUG, "%s: tcp_conn_addref(%p)", conn->name, conn);
+	log_msg(LVL_DEBUG2, "%s: tcp_conn_addref(%p)", conn->name, conn);
 	atomic_inc(&conn->refcnt);
 }
@@ -196,5 +196,5 @@
 void tcp_conn_delref(tcp_conn_t *conn)
 {
-	log_msg(LVL_DEBUG, "%s: tcp_conn_delref(%p)", conn->name, conn);
+	log_msg(LVL_DEBUG2, "%s: tcp_conn_delref(%p)", conn->name, conn);
 
 	if (atomic_predec(&conn->refcnt) == 0)
@@ -312,5 +312,5 @@
 static bool tcp_socket_match(tcp_sock_t *sock, tcp_sock_t *patt)
 {
-	log_msg(LVL_DEBUG, "tcp_socket_match(sock=(%x,%u), pat=(%x,%u))",
+	log_msg(LVL_DEBUG2, "tcp_socket_match(sock=(%x,%u), pat=(%x,%u))",
 	    sock->addr.ipv4, sock->port, patt->addr.ipv4, patt->port);
 
@@ -323,5 +323,5 @@
 		return false;
 
-	log_msg(LVL_DEBUG, " -> match");
+	log_msg(LVL_DEBUG2, " -> match");
 
 	return true;
@@ -331,5 +331,5 @@
 static bool tcp_sockpair_match(tcp_sockpair_t *sp, tcp_sockpair_t *pattern)
 {
-	log_msg(LVL_DEBUG, "tcp_sockpair_match(%p, %p)", sp, pattern);
+	log_msg(LVL_DEBUG2, "tcp_sockpair_match(%p, %p)", sp, pattern);
 
 	if (!tcp_socket_match(&sp->local, &pattern->local))
@@ -360,5 +360,5 @@
 		tcp_conn_t *conn = list_get_instance(link, tcp_conn_t, link);
 		tcp_sockpair_t *csp = &conn->ident;
-		log_msg(LVL_DEBUG, "compare with conn (f:(%x,%u), l:(%x,%u))",
+		log_msg(LVL_DEBUG2, "compare with conn (f:(%x,%u), l:(%x,%u))",
 		    csp->foreign.addr.ipv4, csp->foreign.port,
 		    csp->local.addr.ipv4, csp->local.port);
Index: uspace/srv/net/tcp/ncsim.c
===================================================================
--- uspace/srv/net/tcp/ncsim.c	(revision 422af2b1e7236addac60aba765ad4a3d606b1365)
+++ uspace/srv/net/tcp/ncsim.c	(revision 68f57e1baf7a0ef1d2d7ca7bc3648755a58dcc03)
@@ -44,5 +44,5 @@
 #include <io/log.h>
 #include <stdlib.h>
-#include <thread.h>
+#include <fibril.h>
 #include "conn.h"
 #include "ncsim.h"
@@ -119,6 +119,6 @@
 }
 
-/** Network condition simulator handler thread. */
-static void tcp_ncsim_thread(void *arg)
+/** Network condition simulator handler fibril. */
+static int tcp_ncsim_fibril(void *arg)
 {
 	link_t *link;
@@ -126,5 +126,5 @@
 	int rc;
 
-	log_msg(LVL_DEBUG, "tcp_ncsim_thread()");
+	log_msg(LVL_DEBUG, "tcp_ncsim_fibril()");
 
 
@@ -151,19 +151,23 @@
 		free(sqe);
 	}
+
+	/* Not reached */
+	return 0;
 }
 
-/** Start simulator handler thread. */
-void tcp_ncsim_thread_start(void)
+/** Start simulator handler fibril. */
+void tcp_ncsim_fibril_start(void)
 {
-	thread_id_t tid;
-        int rc;
+	fid_t fid;
 
-	log_msg(LVL_DEBUG, "tcp_ncsim_thread_start()");
+	log_msg(LVL_DEBUG, "tcp_ncsim_fibril_start()");
 
-	rc = thread_create(tcp_ncsim_thread, NULL, "ncsim", &tid);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed creating ncsim thread.");
+	fid = fibril_create(tcp_ncsim_fibril, NULL);
+	if (fid == 0) {
+		log_msg(LVL_ERROR, "Failed creating ncsim fibril.");
 		return;
 	}
+
+	fibril_add_ready(fid);
 }
 
Index: uspace/srv/net/tcp/ncsim.h
===================================================================
--- uspace/srv/net/tcp/ncsim.h	(revision 422af2b1e7236addac60aba765ad4a3d606b1365)
+++ uspace/srv/net/tcp/ncsim.h	(revision 68f57e1baf7a0ef1d2d7ca7bc3648755a58dcc03)
@@ -40,6 +40,5 @@
 extern void tcp_ncsim_init(void);
 extern void tcp_ncsim_bounce_seg(tcp_sockpair_t *, tcp_segment_t *);
-extern void tcp_ncsim_thread_start(void);
-
+extern void tcp_ncsim_fibril_start(void);
 
 #endif
Index: uspace/srv/net/tcp/rqueue.c
===================================================================
--- uspace/srv/net/tcp/rqueue.c	(revision 422af2b1e7236addac60aba765ad4a3d606b1365)
+++ uspace/srv/net/tcp/rqueue.c	(revision 68f57e1baf7a0ef1d2d7ca7bc3648755a58dcc03)
@@ -39,5 +39,5 @@
 #include <io/log.h>
 #include <stdlib.h>
-#include <thread.h>
+#include <fibril.h>
 #include "conn.h"
 #include "pdu.h"
@@ -128,11 +128,11 @@
 }
 
-/** Receive queue handler thread. */
-static void tcp_rqueue_thread(void *arg)
+/** Receive queue handler fibril. */
+static int tcp_rqueue_fibril(void *arg)
 {
 	link_t *link;
 	tcp_rqueue_entry_t *rqe;
 
-	log_msg(LVL_DEBUG, "tcp_rqueue_thread()");
+	log_msg(LVL_DEBUG, "tcp_rqueue_fibril()");
 
 	while (true) {
@@ -142,19 +142,23 @@
 		tcp_as_segment_arrived(&rqe->sp, rqe->seg);
 	}
+
+	/* Not reached */
+	return 0;
 }
 
-/** Start receive queue handler thread. */
-void tcp_rqueue_thread_start(void)
+/** Start receive queue handler fibril. */
+void tcp_rqueue_fibril_start(void)
 {
-	thread_id_t tid;
-        int rc;
+	fid_t fid;
 
-	log_msg(LVL_DEBUG, "tcp_rqueue_thread_start()");
+	log_msg(LVL_DEBUG, "tcp_rqueue_fibril_start()");
 
-	rc = thread_create(tcp_rqueue_thread, NULL, "rqueue", &tid);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed creating rqueue thread.");
+	fid = fibril_create(tcp_rqueue_fibril, NULL);
+	if (fid == 0) {
+		log_msg(LVL_ERROR, "Failed creating rqueue fibril.");
 		return;
 	}
+
+	fibril_add_ready(fid);
 }
 
Index: uspace/srv/net/tcp/rqueue.h
===================================================================
--- uspace/srv/net/tcp/rqueue.h	(revision 422af2b1e7236addac60aba765ad4a3d606b1365)
+++ uspace/srv/net/tcp/rqueue.h	(revision 68f57e1baf7a0ef1d2d7ca7bc3648755a58dcc03)
@@ -42,5 +42,5 @@
 extern void tcp_rqueue_insert_seg(tcp_sockpair_t *, tcp_segment_t *);
 extern void tcp_rqueue_handler(void *);
-extern void tcp_rqueue_thread_start(void);
+extern void tcp_rqueue_fibril_start(void);
 
 
Index: uspace/srv/net/tcp/segment.c
===================================================================
--- uspace/srv/net/tcp/segment.c	(revision 422af2b1e7236addac60aba765ad4a3d606b1365)
+++ uspace/srv/net/tcp/segment.c	(revision 68f57e1baf7a0ef1d2d7ca7bc3648755a58dcc03)
@@ -248,11 +248,11 @@
 void tcp_segment_dump(tcp_segment_t *seg)
 {
-	log_msg(LVL_DEBUG, "Segment dump:");
-	log_msg(LVL_DEBUG, " - ctrl = %u", (unsigned)seg->ctrl);
-	log_msg(LVL_DEBUG, " - seq = % " PRIu32, seg->seq);
-	log_msg(LVL_DEBUG, " - ack = % " PRIu32, seg->ack);
-	log_msg(LVL_DEBUG, " - len = % " PRIu32, seg->len);
-	log_msg(LVL_DEBUG, " - wnd = % " PRIu32, seg->wnd);
-	log_msg(LVL_DEBUG, " - up = % " PRIu32, seg->up);
+	log_msg(LVL_DEBUG2, "Segment dump:");
+	log_msg(LVL_DEBUG2, " - ctrl = %u", (unsigned)seg->ctrl);
+	log_msg(LVL_DEBUG2, " - seq = % " PRIu32, seg->seq);
+	log_msg(LVL_DEBUG2, " - ack = % " PRIu32, seg->ack);
+	log_msg(LVL_DEBUG2, " - len = % " PRIu32, seg->len);
+	log_msg(LVL_DEBUG2, " - wnd = % " PRIu32, seg->wnd);
+	log_msg(LVL_DEBUG2, " - up = % " PRIu32, seg->up);
 }
 
Index: uspace/srv/net/tcp/sock.c
===================================================================
--- uspace/srv/net/tcp/sock.c	(revision 422af2b1e7236addac60aba765ad4a3d606b1365)
+++ uspace/srv/net/tcp/sock.c	(revision 68f57e1baf7a0ef1d2d7ca7bc3648755a58dcc03)
@@ -51,6 +51,4 @@
 #include "ucall.h"
 
-#define FRAGMENT_SIZE 1024
-
 #define MAX_BACKLOG 128
 
@@ -66,4 +64,5 @@
 static void tcp_sock_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg);
 static void tcp_sock_cstate_cb(tcp_conn_t *conn, void *arg);
+static int tcp_sock_recv_fibril(void *arg);
 
 int tcp_sock_init(void)
@@ -97,5 +96,5 @@
 	async_exch_t *exch = async_exchange_begin(sock_core->sess);
 	async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t)sock_core->socket_id,
-	    FRAGMENT_SIZE, 0, 0, 1);
+	    TCP_SOCK_FRAGMENT_SIZE, 0, 0, 1);
 	async_exchange_end(exch);
 }
@@ -106,12 +105,65 @@
 	async_exch_t *exch = async_exchange_begin(lsock_core->sess);
 	async_msg_5(exch, NET_SOCKET_ACCEPTED, (sysarg_t)lsock_core->socket_id,
-	    FRAGMENT_SIZE, 0, 0, 0);
+	    TCP_SOCK_FRAGMENT_SIZE, 0, 0, 0);
 	async_exchange_end(exch);
 }
 
+static int tcp_sock_create(tcp_client_t *client, tcp_sockdata_t **rsock)
+{
+	tcp_sockdata_t *sock;
+
+	log_msg(LVL_DEBUG, "tcp_sock_create()");
+	*rsock = NULL;
+
+	sock = calloc(sizeof(tcp_sockdata_t), 1);
+	if (sock == NULL)
+		return ENOMEM;
+
+	fibril_mutex_initialize(&sock->lock);
+	sock->client = client;
+
+	sock->recv_buffer_used = 0;
+	sock->recv_error = TCP_EOK;
+	fibril_mutex_initialize(&sock->recv_buffer_lock);
+	fibril_condvar_initialize(&sock->recv_buffer_cv);
+	list_initialize(&sock->ready);
+
+	*rsock = sock;
+	return EOK;
+}
+
+static void tcp_sock_uncreate(tcp_sockdata_t *sock)
+{
+	log_msg(LVL_DEBUG, "tcp_sock_uncreate()");
+	free(sock);
+}
+
+static int tcp_sock_finish_setup(tcp_sockdata_t *sock, int *sock_id)
+{
+	socket_core_t *sock_core;
+	int rc;
+
+	log_msg(LVL_DEBUG, "tcp_sock_finish_setup()");
+
+	sock->recv_fibril = fibril_create(tcp_sock_recv_fibril, sock);
+	if (sock->recv_fibril == 0)
+		return ENOMEM;
+
+	rc = socket_create(&sock->client->sockets, sock->client->sess,
+	    sock, sock_id);
+
+	if (rc != EOK)
+		return rc;
+
+	sock_core = socket_cores_find(&sock->client->sockets, *sock_id);
+	assert(sock_core != NULL);
+	sock->sock_core = sock_core;
+
+	return EOK;
+}
+
 static void tcp_sock_socket(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
 {
 	tcp_sockdata_t *sock;
-	socket_core_t *sock_core;
 	int sock_id;
 	int rc;
@@ -119,31 +171,26 @@
 
 	log_msg(LVL_DEBUG, "tcp_sock_socket()");
-	sock = calloc(sizeof(tcp_sockdata_t), 1);
-	if (sock == NULL) {
-		async_answer_0(callid, ENOMEM);
-		return;
-	}
-
-	fibril_mutex_initialize(&sock->lock);
-	sock->client = client;
+
+	rc = tcp_sock_create(client, &sock);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
 	sock->laddr.ipv4 = TCP_IPV4_ANY;
 	sock->lconn = NULL;
 	sock->backlog = 0;
-	list_initialize(&sock->ready);
 
 	sock_id = SOCKET_GET_SOCKET_ID(call);
-	rc = socket_create(&client->sockets, client->sess, sock, &sock_id);
+	rc = tcp_sock_finish_setup(sock, &sock_id);
 	if (rc != EOK) {
+		tcp_sock_uncreate(sock);
 		async_answer_0(callid, rc);
 		return;
 	}
 
-	sock_core = socket_cores_find(&client->sockets, sock_id);
-	assert(sock_core != NULL);
-	sock->sock_core = sock_core;
-
 	SOCKET_SET_SOCKET_ID(answer, sock_id);
 
-	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
+	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, TCP_SOCK_FRAGMENT_SIZE);
 	SOCKET_SET_HEADER_SIZE(answer, sizeof(tcp_header_t));
 	
@@ -361,9 +408,8 @@
 	}
 
+	if (rc == EOK)
+		fibril_add_ready(socket->recv_fibril);
+
 	async_answer_0(callid, rc);
-
-	/* Push one fragment notification to client's queue */
-	tcp_sock_notify_data(sock_core);
-	log_msg(LVL_DEBUG, "tcp_sock_connect(): notify conn\n");
 }
 
@@ -374,5 +420,4 @@
 	int asock_id;
 	socket_core_t *sock_core;
-	socket_core_t *asock_core;
 	tcp_sockdata_t *socket;
 	tcp_sockdata_t *asocket;
@@ -444,33 +489,31 @@
 	/* Allocate socket for accepted connection */
 
-	log_msg(LVL_DEBUG, "tcp_sock_accept(): allocate asocket\n");
-	asocket = calloc(sizeof(tcp_sockdata_t), 1);
-	if (asocket == NULL) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOMEM);
-		return;
-	}
-
-	fibril_mutex_initialize(&asocket->lock);
-	asocket->client = client;
+	rc = tcp_sock_create(client, &asocket);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, rc);
+		return;
+	}
+
 	asocket->conn = conn;
 	log_msg(LVL_DEBUG, "tcp_sock_accept():create asocket\n");
 
-	rc = socket_create(&client->sockets, client->sess, asocket, &asock_id);
+	rc = tcp_sock_finish_setup(asocket, &asock_id);
 	if (rc != EOK) {
+		tcp_sock_uncreate(asocket);
 		fibril_mutex_unlock(&socket->lock);
 		async_answer_0(callid, rc);
 		return;
 	}
+
+	fibril_add_ready(asocket->recv_fibril);
+
 	log_msg(LVL_DEBUG, "tcp_sock_accept(): find acore\n");
 
-	asock_core = socket_cores_find(&client->sockets, asock_id);
-	assert(asock_core != NULL);
-
-	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
+	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, TCP_SOCK_FRAGMENT_SIZE);
 	SOCKET_SET_SOCKET_ID(answer, asock_id);
 	SOCKET_SET_ADDRESS_LENGTH(answer, sizeof(struct sockaddr_in));
 	
-	async_answer_3(callid, asock_core->socket_id,
+	async_answer_3(callid, asocket->sock_core->socket_id,
 	    IPC_GET_ARG1(answer), IPC_GET_ARG2(answer),
 	    IPC_GET_ARG3(answer));
@@ -478,5 +521,4 @@
 	/* Push one fragment notification to client's queue */
 	log_msg(LVL_DEBUG, "tcp_sock_accept(): notify data\n");
-	tcp_sock_notify_data(asock_core);
 	fibril_mutex_unlock(&socket->lock);
 }
@@ -492,5 +534,5 @@
 	ipc_callid_t wcallid;
 	size_t length;
-	uint8_t buffer[FRAGMENT_SIZE];
+	uint8_t buffer[TCP_SOCK_FRAGMENT_SIZE];
 	tcp_error_t trc;
 	int rc;
@@ -523,6 +565,6 @@
 		}
 
-		if (length > FRAGMENT_SIZE)
-			length = FRAGMENT_SIZE;
+		if (length > TCP_SOCK_FRAGMENT_SIZE)
+			length = TCP_SOCK_FRAGMENT_SIZE;
 
 		rc = async_data_write_finalize(wcallid, buffer, length);
@@ -560,5 +602,5 @@
 
 	IPC_SET_ARG1(answer, 0);
-	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
+	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, TCP_SOCK_FRAGMENT_SIZE);
 	async_answer_2(callid, EOK, IPC_GET_ARG1(answer),
 	    IPC_GET_ARG2(answer));
@@ -581,8 +623,5 @@
 	ipc_call_t answer;
 	ipc_callid_t rcallid;
-	uint8_t buffer[FRAGMENT_SIZE];
 	size_t data_len;
-	xflags_t xflags;
-	tcp_error_t trc;
 	struct sockaddr_in addr;
 	tcp_sock_t *rsock;
@@ -611,9 +650,18 @@
 	(void)flags;
 
-	trc = tcp_uc_receive(socket->conn, buffer, FRAGMENT_SIZE, &data_len,
-	    &xflags);
-	log_msg(LVL_DEBUG, "**** tcp_uc_receive done");
-
-	switch (trc) {
+	log_msg(LVL_DEBUG, "tcp_sock_recvfrom(): lock recv_buffer_lock");
+	fibril_mutex_lock(&socket->recv_buffer_lock);
+	while (socket->recv_buffer_used == 0 && socket->recv_error == TCP_EOK) {
+		log_msg(LVL_DEBUG, "wait for recv_buffer_cv + recv_buffer_used != 0");
+		fibril_condvar_wait(&socket->recv_buffer_cv,
+		    &socket->recv_buffer_lock);
+	}
+
+	log_msg(LVL_DEBUG, "Got data in sock recv_buffer");
+
+	data_len = socket->recv_buffer_used;
+	rc = socket->recv_error;
+
+	switch (socket->recv_error) {
 	case TCP_EOK:
 		rc = EOK;
@@ -630,6 +678,7 @@
 	}
 
-	log_msg(LVL_DEBUG, "**** tcp_uc_receive -> %d", rc);
+	log_msg(LVL_DEBUG, "**** recv result -> %d", rc);
 	if (rc != EOK) {
+		fibril_mutex_unlock(&socket->recv_buffer_lock);
 		fibril_mutex_unlock(&socket->lock);
 		async_answer_0(callid, rc);
@@ -646,4 +695,5 @@
 		log_msg(LVL_DEBUG, "addr read receive");
 		if (!async_data_read_receive(&rcallid, &addr_length)) {
+			fibril_mutex_unlock(&socket->recv_buffer_lock);
 			fibril_mutex_unlock(&socket->lock);
 			async_answer_0(callid, EINVAL);
@@ -657,4 +707,5 @@
 		rc = async_data_read_finalize(rcallid, &addr, addr_length);
 		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->recv_buffer_lock);
 			fibril_mutex_unlock(&socket->lock);
 			async_answer_0(callid, EINVAL);
@@ -665,4 +716,5 @@
 	log_msg(LVL_DEBUG, "data read receive");
 	if (!async_data_read_receive(&rcallid, &length)) {
+		fibril_mutex_unlock(&socket->recv_buffer_lock);
 		fibril_mutex_unlock(&socket->lock);
 		async_answer_0(callid, EINVAL);
@@ -674,5 +726,16 @@
 
 	log_msg(LVL_DEBUG, "data read finalize");
-	rc = async_data_read_finalize(rcallid, buffer, length);
+	rc = async_data_read_finalize(rcallid, socket->recv_buffer, length);
+
+	socket->recv_buffer_used -= length;
+	log_msg(LVL_DEBUG, "tcp_sock_recvfrom: %zu left in buffer",
+	    socket->recv_buffer_used);
+	if (socket->recv_buffer_used > 0) {
+		memmove(socket->recv_buffer, socket->recv_buffer + length,
+		    socket->recv_buffer_used);
+		tcp_sock_notify_data(socket->sock_core);
+	}
+
+	fibril_condvar_broadcast(&socket->recv_buffer_cv);
 
 	if (length < data_len && rc == EOK)
@@ -681,7 +744,6 @@
 	SOCKET_SET_READ_DATA_LENGTH(answer, length);
 	async_answer_1(callid, EOK, IPC_GET_ARG1(answer));
-	
-	/* Push one fragment notification to client's queue */
-	tcp_sock_notify_data(sock_core);
+
+	fibril_mutex_unlock(&socket->recv_buffer_lock);
 	fibril_mutex_unlock(&socket->lock);
 }
@@ -694,7 +756,4 @@
 	tcp_error_t trc;
 	int rc;
-	uint8_t buffer[FRAGMENT_SIZE];
-	size_t data_len;
-	xflags_t xflags;
 
 	log_msg(LVL_DEBUG, "tcp_sock_close()");
@@ -717,12 +776,4 @@
 			return;
 		}
-
-		/* Drain incoming data. This should really be done in the background. */
-		do {
-			trc = tcp_uc_receive(socket->conn, buffer,
-			    FRAGMENT_SIZE, &data_len, &xflags);
-		} while (trc == TCP_EOK);
-
-		tcp_uc_delete(socket->conn);
 	}
 
@@ -776,4 +827,44 @@
 	tcp_sock_notify_aconn(socket->sock_core);
 	fibril_mutex_unlock(&socket->lock);
+}
+
+static int tcp_sock_recv_fibril(void *arg)
+{
+	tcp_sockdata_t *sock = (tcp_sockdata_t *)arg;
+	size_t data_len;
+	xflags_t xflags;
+	tcp_error_t trc;
+
+	log_msg(LVL_DEBUG, "tcp_sock_recv_fibril()");
+
+	while (true) {
+		log_msg(LVL_DEBUG, "call tcp_uc_receive()");
+		fibril_mutex_lock(&sock->recv_buffer_lock);
+		while (sock->recv_buffer_used != 0)
+			fibril_condvar_wait(&sock->recv_buffer_cv,
+			    &sock->recv_buffer_lock);
+
+		trc = tcp_uc_receive(sock->conn, sock->recv_buffer,
+		    TCP_SOCK_FRAGMENT_SIZE, &data_len, &xflags);
+
+		if (trc != TCP_EOK) {
+			sock->recv_error = trc;
+			fibril_condvar_broadcast(&sock->recv_buffer_cv);
+			fibril_mutex_unlock(&sock->recv_buffer_lock);
+			tcp_sock_notify_data(sock->sock_core);
+			break;
+		}
+
+		log_msg(LVL_DEBUG, "got data - broadcast recv_buffer_cv");
+
+		sock->recv_buffer_used = data_len;
+		fibril_condvar_broadcast(&sock->recv_buffer_cv);
+		fibril_mutex_unlock(&sock->recv_buffer_lock);
+		tcp_sock_notify_data(sock->sock_core);
+	}
+
+	tcp_uc_delete(sock->conn);
+
+	return 0;
 }
 
Index: uspace/srv/net/tcp/tcp.c
===================================================================
--- uspace/srv/net/tcp/tcp.c	(revision 422af2b1e7236addac60aba765ad4a3d606b1365)
+++ uspace/srv/net/tcp/tcp.c	(revision 68f57e1baf7a0ef1d2d7ca7bc3648755a58dcc03)
@@ -180,8 +180,8 @@
 
 	tcp_rqueue_init();
-	tcp_rqueue_thread_start();
+	tcp_rqueue_fibril_start();
 
 	tcp_ncsim_init();
-	tcp_ncsim_thread_start();
+	tcp_ncsim_fibril_start();
 
 	if (0) tcp_test();
Index: uspace/srv/net/tcp/tcp_type.h
===================================================================
--- uspace/srv/net/tcp/tcp_type.h	(revision 422af2b1e7236addac60aba765ad4a3d606b1365)
+++ uspace/srv/net/tcp/tcp_type.h	(revision 68f57e1baf7a0ef1d2d7ca7bc3648755a58dcc03)
@@ -39,4 +39,5 @@
 #include <async.h>
 #include <bool.h>
+#include <fibril.h>
 #include <fibril_synch.h>
 #include <socket_core.h>
@@ -331,4 +332,6 @@
 } tcp_client_t;
 
+#define TCP_SOCK_FRAGMENT_SIZE 1024
+
 typedef struct tcp_sockdata {
 	/** Lock */
@@ -348,4 +351,11 @@
 	/** List of connections (from lconn) that are ready to be accepted */
 	list_t ready;
+	/** Receiving fibril */
+	fid_t recv_fibril;
+	uint8_t recv_buffer[TCP_SOCK_FRAGMENT_SIZE];
+	size_t recv_buffer_used;
+	fibril_mutex_t recv_buffer_lock;
+	fibril_condvar_t recv_buffer_cv;
+	tcp_error_t recv_error;
 } tcp_sockdata_t;
 
Index: uspace/srv/net/tcp/test.c
===================================================================
--- uspace/srv/net/tcp/test.c	(revision 422af2b1e7236addac60aba765ad4a3d606b1365)
+++ uspace/srv/net/tcp/test.c	(revision 68f57e1baf7a0ef1d2d7ca7bc3648755a58dcc03)
@@ -38,5 +38,5 @@
 #include <errno.h>
 #include <stdio.h>
-#include <thread.h>
+#include <fibril.h>
 #include <str.h>
 #include "tcp_type.h"
@@ -47,5 +47,5 @@
 #define RCV_BUF_SIZE 64
 
-static void test_srv(void *arg)
+static int test_srv(void *arg)
 {
 	tcp_conn_t *conn;
@@ -84,7 +84,8 @@
 
 	printf("test_srv() terminating\n");
+	return 0;
 }
 
-static void test_cli(void *arg)
+static int test_cli(void *arg)
 {
 	tcp_conn_t *conn;
@@ -112,11 +113,12 @@
 	printf("C: User close...\n");
 	tcp_uc_close(conn);
+
+	return 0;
 }
 
 void tcp_test(void)
 {
-	thread_id_t srv_tid;
-	thread_id_t cli_tid;
-	int rc;
+	fid_t srv_fid;
+	fid_t cli_fid;
 
 	printf("tcp_test()\n");
@@ -125,17 +127,21 @@
 
 	if (0) {
-		rc = thread_create(test_srv, NULL, "test_srv", &srv_tid);
-		if (rc != EOK) {
-			printf("Failed to create server thread.\n");
+		srv_fid = fibril_create(test_srv, NULL);
+		if (srv_fid == 0) {
+			printf("Failed to create server fibril.\n");
 			return;
 		}
+
+		fibril_add_ready(srv_fid);
 	}
 
 	if (0) {
-		rc = thread_create(test_cli, NULL, "test_cli", &cli_tid);
-		if (rc != EOK) {
-			printf("Failed to create client thread.\n");
+		cli_fid = fibril_create(test_cli, NULL);
+		if (cli_fid == 0) {
+			printf("Failed to create client fibril.\n");
 			return;
 		}
+
+		fibril_add_ready(cli_fid);
 	}
 }
