Index: kernel/generic/include/cap/cap.h
===================================================================
--- kernel/generic/include/cap/cap.h	(revision 14741a052be3c43773bb8026e9e9ba796d56c4fb)
+++ kernel/generic/include/cap/cap.h	(revision 35f2bb1b3679723dd054eb5ad1d361a7a1b33ef6)
@@ -53,12 +53,15 @@
 
 typedef enum {
+	KOBJECT_TYPE_CALL,
+	KOBJECT_TYPE_IRQ,
 	KOBJECT_TYPE_PHONE,
-	KOBJECT_TYPE_IRQ,
 	KOBJECT_TYPE_MAX
 } kobject_type_t;
 
 struct task;
+
+struct call;
+struct irq;
 struct phone;
-struct irq;
 
 struct kobject;
@@ -79,6 +82,7 @@
 	union {
 		void *raw;
+		struct call *call;
+		struct irq *irq;
 		struct phone *phone;
-		struct irq *irq;
 	};
 } kobject_t;
Index: kernel/generic/include/ipc/ipc.h
===================================================================
--- kernel/generic/include/ipc/ipc.h	(revision 14741a052be3c43773bb8026e9e9ba796d56c4fb)
+++ kernel/generic/include/ipc/ipc.h	(revision 35f2bb1b3679723dd054eb5ad1d361a7a1b33ef6)
@@ -109,4 +109,6 @@
 
 typedef struct {
+	kobject_t *kobject;
+
 	/**
 	 * Task link.
@@ -115,6 +117,4 @@
 	 */
 	link_t ta_link;
-
-	atomic_t refcnt;
 
 	/** Answerbox link. */
Index: kernel/generic/src/ipc/ipc.c
===================================================================
--- kernel/generic/src/ipc/ipc.c	(revision 14741a052be3c43773bb8026e9e9ba796d56c4fb)
+++ kernel/generic/src/ipc/ipc.c	(revision 35f2bb1b3679723dd054eb5ad1d361a7a1b33ef6)
@@ -87,19 +87,18 @@
 }
 
-void ipc_call_hold(call_t *call)
-{
-	atomic_inc(&call->refcnt);
-}
-
-void ipc_call_release(call_t *call)
-{
-	if (atomic_predec(&call->refcnt) == 0) {
-		if (call->buffer)
-			free(call->buffer);
-		if (call->caller_phone)
-			kobject_put(call->caller_phone->kobject);
-		slab_free(call_slab, call);
-	}
-}
+static void call_destroy(void *arg)
+{
+	call_t *call = (call_t *) arg;
+
+	if (call->buffer)
+		free(call->buffer);
+	if (call->caller_phone)
+		kobject_put(call->caller_phone->kobject);
+	slab_free(call_slab, call);
+}
+
+static kobject_ops_t call_kobject_ops = {
+	.destroy = call_destroy
+};
 
 /** Allocate and initialize a call structure.
@@ -117,20 +116,17 @@
 {
 	call_t *call = slab_alloc(call_slab, flags);
-	if (call) {
-		_ipc_call_init(call);
-		ipc_call_hold(call);
-	}
+	if (!call)
+		return NULL;
+	kobject_t *kobj = (kobject_t *) malloc(sizeof(kobject_t), flags);
+	if (!kobj) {
+		slab_free(call_slab, call);
+		return NULL;
+	}
+
+	_ipc_call_init(call);
+	kobject_initialize(kobj, KOBJECT_TYPE_CALL, call, &call_kobject_ops);
+	call->kobject = kobj;
 	
 	return call;
-}
-
-/** Deallocate a call structure.
- *
- * @param call Call structure to be freed.
- *
- */
-void ipc_call_free(call_t *call)
-{
-	ipc_call_release(call);
 }
 
@@ -290,5 +286,5 @@
 		/* This is a forgotten call and call->sender is not valid. */
 		spinlock_unlock(&call->forget_lock);
-		ipc_call_free(call);
+		kobject_put(call->kobject);
 		return;
 	} else {
@@ -705,5 +701,5 @@
 	 * must hold a reference to it.
 	 */
-	ipc_call_hold(call);
+	kobject_add_ref(call->kobject);
 
 	spinlock_unlock(&call->forget_lock);
@@ -714,5 +710,5 @@
 	SYSIPC_OP(request_forget, call);
 
-	ipc_call_release(call);
+	kobject_put(call->kobject);
 }
 
@@ -822,5 +818,5 @@
 	SYSIPC_OP(answer_process, call);
 
-	ipc_call_free(call);
+	kobject_put(call->kobject);
 	goto restart;
 }
Index: kernel/generic/src/ipc/sysipc.c
===================================================================
--- kernel/generic/src/ipc/sysipc.c	(revision 14741a052be3c43773bb8026e9e9ba796d56c4fb)
+++ kernel/generic/src/ipc/sysipc.c	(revision 35f2bb1b3679723dd054eb5ad1d361a7a1b33ef6)
@@ -286,10 +286,10 @@
 #endif
 
-		ipc_call_hold(call);
+		kobject_add_ref(call->kobject);
 		rc = ipc_call_sync(kobj->phone, call);
 		spinlock_lock(&call->forget_lock);
 		bool forgotten = call->forget;
 		spinlock_unlock(&call->forget_lock);
-		ipc_call_release(call);
+		kobject_put(call->kobject);
 
 #ifdef CONFIG_UDEBUG
@@ -306,5 +306,5 @@
 				 * deallocation.
 				 */
-				ipc_call_free(call);
+				kobject_put(call->kobject);
 			} else {
 				/*
@@ -323,5 +323,5 @@
 	
 	memcpy(data->args, call->data.args, sizeof(data->args));
-	ipc_call_free(call);
+	kobject_put(call->kobject);
 	kobject_put(kobj);
 	
@@ -420,5 +420,5 @@
 	    sizeof(call->data.args));
 	if (rc != 0) {
-		ipc_call_free(call);
+		kobject_put(call->kobject);
 		kobject_put(kobj);
 		return (sysarg_t) rc;
@@ -753,5 +753,5 @@
 		STRUCT_TO_USPACE(calldata, &call->data);
 		
-		ipc_call_free(call);
+		kobject_put(call->kobject);
 		
 		return ((sysarg_t) call) | IPC_CALLID_NOTIFICATION;
@@ -762,10 +762,10 @@
 		
 		if (call->flags & IPC_CALL_DISCARD_ANSWER) {
-			ipc_call_free(call);
+			kobject_put(call->kobject);
 			goto restart;
 		}
 		
 		STRUCT_TO_USPACE(calldata, &call->data);
-		ipc_call_free(call);
+		kobject_put(call->kobject);
 		
 		return ((sysarg_t) call) | IPC_CALLID_ANSWERED;
