net: ipc_router: Add snapshot of IPC Router

This snapshot is taken as of msm-4.4 'commit <d2afad6a903b>
("Merge "ext4 crypto: enable HW based encryption with ICE"")'.

Additionally fix the code style warnings and errors.

CRs-Fixed: 1079350
Change-Id: I0972e0a42d12659fc854dce2491df3016704d756
Signed-off-by: Karthikeyan Ramasubramanian <kramasub@codeaurora.org>
diff --git a/net/ipc_router/ipc_router_socket.c b/net/ipc_router/ipc_router_socket.c
new file mode 100644
index 0000000..a84fc11
--- /dev/null
+++ b/net/ipc_router/ipc_router_socket.c
@@ -0,0 +1,681 @@
+/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/net.h>
+#include <linux/socket.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/poll.h>
+#include <linux/fcntl.h>
+#include <linux/gfp.h>
+#include <linux/msm_ipc.h>
+#include <linux/sched.h>
+#include <linux/thread_info.h>
+#include <linux/slab.h>
+#include <linux/kmemleak.h>
+#include <linux/ipc_logging.h>
+#include <linux/string.h>
+#include <linux/atomic.h>
+#include <linux/ipc_router.h>
+
+#include <net/sock.h>
+
+#include "ipc_router_private.h"
+#include "ipc_router_security.h"
+
+#define msm_ipc_sk(sk) ((struct msm_ipc_sock *)(sk))
+#define msm_ipc_sk_port(sk) ((struct msm_ipc_port *)(msm_ipc_sk(sk)->port))
+
+#ifndef SIZE_MAX
+#define SIZE_MAX ((size_t)-1)
+#endif
+
+static int sockets_enabled;
+static struct proto msm_ipc_proto;
+static const struct proto_ops msm_ipc_proto_ops;
+static RAW_NOTIFIER_HEAD(ipcrtr_af_init_chain);
+static DEFINE_MUTEX(ipcrtr_af_init_lock);
+
+static struct sk_buff_head *msm_ipc_router_build_msg(struct msghdr *m,
+						     size_t total_len)
+{
+	struct sk_buff_head *msg_head;
+	struct sk_buff *msg;
+	int first = 1;
+	int last = 1;
+	size_t data_size = 0;
+	size_t alloc_size, align_size;
+	void *data;
+	size_t total_copied_size = 0, copied_size;
+
+	if (iov_iter_count(&m->msg_iter) == total_len)
+		data_size = total_len;
+
+	if (!data_size)
+		return NULL;
+	align_size = ALIGN_SIZE(data_size);
+
+	msg_head = kmalloc(sizeof(*msg_head), GFP_KERNEL);
+	if (!msg_head) {
+		IPC_RTR_ERR("%s: cannot allocate skb_head\n", __func__);
+		return NULL;
+	}
+	skb_queue_head_init(msg_head);
+
+	while (total_copied_size < total_len) {
+		alloc_size = data_size;
+		if (first)
+			alloc_size += IPC_ROUTER_HDR_SIZE;
+		if (last)
+			alloc_size += align_size;
+
+		msg = alloc_skb(alloc_size, GFP_KERNEL);
+		if (!msg) {
+			if (alloc_size <= (PAGE_SIZE / 2)) {
+				IPC_RTR_ERR("%s: cannot allocated skb\n",
+					    __func__);
+				goto msg_build_failure;
+			}
+			data_size = data_size / 2;
+			last = 0;
+			continue;
+		}
+
+		if (first) {
+			skb_reserve(msg, IPC_ROUTER_HDR_SIZE);
+			first = 0;
+		}
+
+		data = skb_put(msg, data_size);
+		copied_size = copy_from_iter(msg->data, data_size,
+					     &m->msg_iter);
+		if (copied_size != data_size) {
+			IPC_RTR_ERR("%s: copy_from_iter failed %zu %zu %zu\n",
+				    __func__, alloc_size, data_size,
+				    copied_size);
+			kfree_skb(msg);
+			goto msg_build_failure;
+		}
+		skb_queue_tail(msg_head, msg);
+		total_copied_size += data_size;
+		data_size = total_len - total_copied_size;
+		last = 1;
+	}
+	return msg_head;
+
+msg_build_failure:
+	while (!skb_queue_empty(msg_head)) {
+		msg = skb_dequeue(msg_head);
+		kfree_skb(msg);
+	}
+	kfree(msg_head);
+	return NULL;
+}
+
+static int msm_ipc_router_extract_msg(struct msghdr *m,
+				      struct rr_packet *pkt)
+{
+	struct sockaddr_msm_ipc *addr;
+	struct rr_header_v1 *hdr;
+	struct sk_buff *temp;
+	union rr_control_msg *ctl_msg;
+	int offset = 0, data_len = 0, copy_len, copied_len;
+
+	if (!m || !pkt) {
+		IPC_RTR_ERR("%s: Invalid pointers passed\n", __func__);
+		return -EINVAL;
+	}
+	addr = (struct sockaddr_msm_ipc *)m->msg_name;
+
+	hdr = &pkt->hdr;
+	if (addr && (hdr->type == IPC_ROUTER_CTRL_CMD_RESUME_TX)) {
+		temp = skb_peek(pkt->pkt_fragment_q);
+		ctl_msg = (union rr_control_msg *)(temp->data);
+		addr->family = AF_MSM_IPC;
+		addr->address.addrtype = MSM_IPC_ADDR_ID;
+		addr->address.addr.port_addr.node_id = ctl_msg->cli.node_id;
+		addr->address.addr.port_addr.port_id = ctl_msg->cli.port_id;
+		m->msg_namelen = sizeof(struct sockaddr_msm_ipc);
+		return offset;
+	}
+	if (addr && (hdr->type == IPC_ROUTER_CTRL_CMD_DATA)) {
+		addr->family = AF_MSM_IPC;
+		addr->address.addrtype = MSM_IPC_ADDR_ID;
+		addr->address.addr.port_addr.node_id = hdr->src_node_id;
+		addr->address.addr.port_addr.port_id = hdr->src_port_id;
+		m->msg_namelen = sizeof(struct sockaddr_msm_ipc);
+	}
+
+	data_len = hdr->size;
+	skb_queue_walk(pkt->pkt_fragment_q, temp) {
+		copy_len = data_len < temp->len ? data_len : temp->len;
+		copied_len = copy_to_iter(temp->data, copy_len, &m->msg_iter);
+		if (copy_len != copied_len) {
+			IPC_RTR_ERR("%s: Copy to user failed\n", __func__);
+			return -EFAULT;
+		}
+		offset += copy_len;
+		data_len -= copy_len;
+	}
+	return offset;
+}
+
+static int msm_ipc_router_create(struct net *net,
+				 struct socket *sock,
+				 int protocol,
+				 int kern)
+{
+	struct sock *sk;
+	struct msm_ipc_port *port_ptr;
+
+	if (unlikely(protocol != 0)) {
+		IPC_RTR_ERR("%s: Protocol not supported\n", __func__);
+		return -EPROTONOSUPPORT;
+	}
+
+	switch (sock->type) {
+	case SOCK_DGRAM:
+		break;
+	default:
+		IPC_RTR_ERR("%s: Protocol type not supported\n", __func__);
+		return -EPROTOTYPE;
+	}
+
+	sk = sk_alloc(net, AF_MSM_IPC, GFP_KERNEL, &msm_ipc_proto, kern);
+	if (!sk) {
+		IPC_RTR_ERR("%s: sk_alloc failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	sock->ops = &msm_ipc_proto_ops;
+	sock_init_data(sock, sk);
+	sk->sk_data_ready = NULL;
+	sk->sk_write_space = ipc_router_dummy_write_space;
+	sk->sk_rcvtimeo = DEFAULT_RCV_TIMEO;
+	sk->sk_sndtimeo = DEFAULT_SND_TIMEO;
+
+	port_ptr = msm_ipc_router_create_raw_port(sk, NULL, NULL);
+	if (!port_ptr) {
+		IPC_RTR_ERR("%s: port_ptr alloc failed\n", __func__);
+		sock_put(sk);
+		sock->sk = NULL;
+		return -ENOMEM;
+	}
+
+	port_ptr->check_send_permissions = msm_ipc_check_send_permissions;
+	msm_ipc_sk(sk)->port = port_ptr;
+	msm_ipc_sk(sk)->default_node_vote_info = NULL;
+
+	return 0;
+}
+
+int msm_ipc_router_bind(struct socket *sock, struct sockaddr *uaddr,
+			int uaddr_len)
+{
+	struct sockaddr_msm_ipc *addr = (struct sockaddr_msm_ipc *)uaddr;
+	struct sock *sk = sock->sk;
+	struct msm_ipc_port *port_ptr;
+	int ret;
+
+	if (!sk)
+		return -EINVAL;
+
+	if (!check_permissions()) {
+		IPC_RTR_ERR("%s: %s Do not have permissions\n",
+			    __func__, current->comm);
+		return -EPERM;
+	}
+
+	if (!uaddr_len) {
+		IPC_RTR_ERR("%s: Invalid address length\n", __func__);
+		return -EINVAL;
+	}
+
+	if (addr->family != AF_MSM_IPC) {
+		IPC_RTR_ERR("%s: Address family is incorrect\n", __func__);
+		return -EAFNOSUPPORT;
+	}
+
+	if (addr->address.addrtype != MSM_IPC_ADDR_NAME) {
+		IPC_RTR_ERR("%s: Address type is incorrect\n", __func__);
+		return -EINVAL;
+	}
+
+	port_ptr = msm_ipc_sk_port(sk);
+	if (!port_ptr)
+		return -ENODEV;
+
+	if (!msm_ipc_sk(sk)->default_node_vote_info)
+		msm_ipc_sk(sk)->default_node_vote_info =
+			msm_ipc_load_default_node();
+	lock_sock(sk);
+
+	ret = msm_ipc_router_register_server(port_ptr, &addr->address);
+
+	release_sock(sk);
+	return ret;
+}
+
+static int ipc_router_connect(struct socket *sock, struct sockaddr *uaddr,
+			      int uaddr_len, int flags)
+{
+	struct sockaddr_msm_ipc *addr = (struct sockaddr_msm_ipc *)uaddr;
+	struct sock *sk = sock->sk;
+	struct msm_ipc_port *port_ptr;
+	int ret;
+
+	if (!sk)
+		return -EINVAL;
+
+	if (uaddr_len <= 0) {
+		IPC_RTR_ERR("%s: Invalid address length\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!addr) {
+		IPC_RTR_ERR("%s: Invalid address\n", __func__);
+		return -EINVAL;
+	}
+
+	if (addr->family != AF_MSM_IPC) {
+		IPC_RTR_ERR("%s: Address family is incorrect\n", __func__);
+		return -EAFNOSUPPORT;
+	}
+
+	port_ptr = msm_ipc_sk_port(sk);
+	if (!port_ptr)
+		return -ENODEV;
+
+	lock_sock(sk);
+	ret = ipc_router_set_conn(port_ptr, &addr->address);
+	release_sock(sk);
+	return ret;
+}
+
+static int msm_ipc_router_sendmsg(struct socket *sock,
+				  struct msghdr *m, size_t total_len)
+{
+	struct sock *sk = sock->sk;
+	struct msm_ipc_port *port_ptr = msm_ipc_sk_port(sk);
+	struct sockaddr_msm_ipc *dest = (struct sockaddr_msm_ipc *)m->msg_name;
+	struct sk_buff_head *msg;
+	int ret;
+	struct msm_ipc_addr dest_addr = {0};
+	long timeout;
+
+	if (dest) {
+		if (m->msg_namelen < sizeof(*dest) ||
+		    dest->family != AF_MSM_IPC)
+			return -EINVAL;
+		memcpy(&dest_addr, &dest->address, sizeof(dest_addr));
+	} else {
+		if (port_ptr->conn_status == NOT_CONNECTED)
+			return -EDESTADDRREQ;
+		if (port_ptr->conn_status < CONNECTION_RESET)
+			return -ENETRESET;
+		memcpy(&dest_addr.addr.port_addr, &port_ptr->dest_addr,
+		       sizeof(struct msm_ipc_port_addr));
+		dest_addr.addrtype = MSM_IPC_ADDR_ID;
+	}
+
+	if (total_len > MAX_IPC_PKT_SIZE)
+		return -EINVAL;
+
+	lock_sock(sk);
+	timeout = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT);
+	msg = msm_ipc_router_build_msg(m, total_len);
+	if (!msg) {
+		IPC_RTR_ERR("%s: Msg build failure\n", __func__);
+		ret = -ENOMEM;
+		goto out_sendmsg;
+	}
+	kmemleak_not_leak(msg);
+
+	if (port_ptr->type == CLIENT_PORT)
+		wait_for_irsc_completion();
+	ret = msm_ipc_router_send_to(port_ptr, msg, &dest_addr, timeout);
+	if (ret != total_len) {
+		if (ret < 0) {
+			if (ret != -EAGAIN)
+				IPC_RTR_ERR("%s: Send_to failure %d\n",
+					    __func__, ret);
+			msm_ipc_router_free_skb(msg);
+		} else if (ret >= 0) {
+			ret = -EFAULT;
+		}
+	}
+
+out_sendmsg:
+	release_sock(sk);
+	return ret;
+}
+
+static int msm_ipc_router_recvmsg(struct socket *sock,
+				  struct msghdr *m, size_t buf_len, int flags)
+{
+	struct sock *sk = sock->sk;
+	struct msm_ipc_port *port_ptr = msm_ipc_sk_port(sk);
+	struct rr_packet *pkt;
+	long timeout;
+	int ret;
+
+	lock_sock(sk);
+	if (!buf_len) {
+		if (flags & MSG_PEEK)
+			ret = msm_ipc_router_get_curr_pkt_size(port_ptr);
+		else
+			ret = -EINVAL;
+		release_sock(sk);
+		return ret;
+	}
+	timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
+
+	ret = msm_ipc_router_rx_data_wait(port_ptr, timeout);
+	if (ret) {
+		release_sock(sk);
+		if (ret == -ENOMSG)
+			m->msg_namelen = 0;
+		return ret;
+	}
+
+	ret = msm_ipc_router_read(port_ptr, &pkt, buf_len);
+	if (ret <= 0 || !pkt) {
+		release_sock(sk);
+		return ret;
+	}
+
+	ret = msm_ipc_router_extract_msg(m, pkt);
+	release_pkt(pkt);
+	release_sock(sk);
+	return ret;
+}
+
+static int msm_ipc_router_ioctl(struct socket *sock,
+				unsigned int cmd, unsigned long arg)
+{
+	struct sock *sk = sock->sk;
+	struct msm_ipc_port *port_ptr;
+	struct server_lookup_args server_arg;
+	struct msm_ipc_server_info *srv_info = NULL;
+	unsigned int n;
+	size_t srv_info_sz = 0;
+	int ret;
+
+	if (!sk)
+		return -EINVAL;
+
+	lock_sock(sk);
+	port_ptr = msm_ipc_sk_port(sock->sk);
+	if (!port_ptr) {
+		release_sock(sk);
+		return -EINVAL;
+	}
+
+	switch (cmd) {
+	case IPC_ROUTER_IOCTL_GET_VERSION:
+		n = IPC_ROUTER_V1;
+		ret = put_user(n, (unsigned int *)arg);
+		break;
+
+	case IPC_ROUTER_IOCTL_GET_MTU:
+		n = (MAX_IPC_PKT_SIZE - IPC_ROUTER_HDR_SIZE);
+		ret = put_user(n, (unsigned int *)arg);
+		break;
+
+	case IPC_ROUTER_IOCTL_GET_CURR_PKT_SIZE:
+		ret = msm_ipc_router_get_curr_pkt_size(port_ptr);
+		break;
+
+	case IPC_ROUTER_IOCTL_LOOKUP_SERVER:
+		if (!msm_ipc_sk(sk)->default_node_vote_info)
+			msm_ipc_sk(sk)->default_node_vote_info =
+				msm_ipc_load_default_node();
+
+		ret = copy_from_user(&server_arg, (void *)arg,
+				     sizeof(server_arg));
+		if (ret) {
+			ret = -EFAULT;
+			break;
+		}
+
+		if (server_arg.num_entries_in_array < 0) {
+			ret = -EINVAL;
+			break;
+		}
+		if (server_arg.num_entries_in_array) {
+			if (server_arg.num_entries_in_array >
+				(SIZE_MAX / sizeof(*srv_info))) {
+				IPC_RTR_ERR("%s: Integer Overflow %zu * %d\n",
+					    __func__, sizeof(*srv_info),
+					server_arg.num_entries_in_array);
+				ret = -EINVAL;
+				break;
+			}
+			srv_info_sz = server_arg.num_entries_in_array *
+					sizeof(*srv_info);
+			srv_info = kmalloc(srv_info_sz, GFP_KERNEL);
+			if (!srv_info) {
+				ret = -ENOMEM;
+				break;
+			}
+		}
+		ret = msm_ipc_router_lookup_server_name
+				(&server_arg.port_name, srv_info,
+				server_arg.num_entries_in_array,
+				server_arg.lookup_mask);
+		if (ret < 0) {
+			IPC_RTR_ERR("%s: Server not found\n", __func__);
+			ret = -ENODEV;
+			kfree(srv_info);
+			break;
+		}
+		server_arg.num_entries_found = ret;
+
+		ret = copy_to_user((void *)arg, &server_arg,
+				   sizeof(server_arg));
+
+		n = min(server_arg.num_entries_found,
+			server_arg.num_entries_in_array);
+
+		if (ret == 0 && n) {
+			ret = copy_to_user((void *)(arg + sizeof(server_arg)),
+					   srv_info, n * sizeof(*srv_info));
+		}
+
+		if (ret)
+			ret = -EFAULT;
+		kfree(srv_info);
+		break;
+
+	case IPC_ROUTER_IOCTL_BIND_CONTROL_PORT:
+		ret = msm_ipc_router_bind_control_port(port_ptr);
+		break;
+
+	case IPC_ROUTER_IOCTL_CONFIG_SEC_RULES:
+		ret = msm_ipc_config_sec_rules((void *)arg);
+		if (ret != -EPERM)
+			port_ptr->type = IRSC_PORT;
+		break;
+
+	default:
+		ret = -EINVAL;
+	}
+	release_sock(sk);
+	return ret;
+}
+
+static unsigned int msm_ipc_router_poll(struct file *file, struct socket *sock,
+					poll_table *wait)
+{
+	struct sock *sk = sock->sk;
+	struct msm_ipc_port *port_ptr;
+	u32 mask = 0;
+
+	if (!sk)
+		return -EINVAL;
+
+	port_ptr = msm_ipc_sk_port(sk);
+	if (!port_ptr)
+		return -EINVAL;
+
+	poll_wait(file, &port_ptr->port_rx_wait_q, wait);
+
+	if (!list_empty(&port_ptr->port_rx_q))
+		mask |= (POLLRDNORM | POLLIN);
+
+	if (port_ptr->conn_status == CONNECTION_RESET)
+		mask |= (POLLHUP | POLLERR);
+
+	return mask;
+}
+
+static int msm_ipc_router_close(struct socket *sock)
+{
+	struct sock *sk = sock->sk;
+	struct msm_ipc_port *port_ptr = msm_ipc_sk_port(sk);
+	int ret;
+
+	lock_sock(sk);
+	ret = msm_ipc_router_close_port(port_ptr);
+	msm_ipc_unload_default_node(msm_ipc_sk(sk)->default_node_vote_info);
+	release_sock(sk);
+	sock_put(sk);
+	sock->sk = NULL;
+
+	return ret;
+}
+
+/**
+ * register_ipcrtr_af_init_notifier() - Register for ipc router socket
+ *				address family initialization callback
+ * @nb: Notifier block which will be notified when address family is
+ *	initialized.
+ *
+ * Return: 0 on success, standard error code otherwise.
+ */
+int register_ipcrtr_af_init_notifier(struct notifier_block *nb)
+{
+	int ret;
+
+	if (!nb)
+		return -EINVAL;
+	mutex_lock(&ipcrtr_af_init_lock);
+	if (sockets_enabled)
+		nb->notifier_call(nb, IPCRTR_AF_INIT, NULL);
+	ret = raw_notifier_chain_register(&ipcrtr_af_init_chain, nb);
+	mutex_unlock(&ipcrtr_af_init_lock);
+	return ret;
+}
+EXPORT_SYMBOL(register_ipcrtr_af_init_notifier);
+
+/**
+ * unregister_ipcrtr_af_init_notifier() - Unregister for ipc router socket
+ *				address family initialization callback
+ * @nb: Notifier block which will be notified once address family is
+ *	initialized.
+ *
+ * Return: 0 on success, standard error code otherwise.
+ */
+int unregister_ipcrtr_af_init_notifier(struct notifier_block *nb)
+{
+	int ret;
+
+	if (!nb)
+		return -EINVAL;
+	ret = raw_notifier_chain_unregister(&ipcrtr_af_init_chain, nb);
+	return ret;
+}
+EXPORT_SYMBOL(unregister_ipcrtr_af_init_notifier);
+
+static const struct net_proto_family msm_ipc_family_ops = {
+	.owner		= THIS_MODULE,
+	.family		= AF_MSM_IPC,
+	.create		= msm_ipc_router_create
+};
+
+static const struct proto_ops msm_ipc_proto_ops = {
+	.family			= AF_MSM_IPC,
+	.owner			= THIS_MODULE,
+	.release		= msm_ipc_router_close,
+	.bind			= msm_ipc_router_bind,
+	.connect		= ipc_router_connect,
+	.socketpair		= sock_no_socketpair,
+	.accept			= sock_no_accept,
+	.getname		= sock_no_getname,
+	.poll			= msm_ipc_router_poll,
+	.ioctl			= msm_ipc_router_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl		= msm_ipc_router_ioctl,
+#endif
+	.listen			= sock_no_listen,
+	.shutdown		= sock_no_shutdown,
+	.setsockopt		= sock_no_setsockopt,
+	.getsockopt		= sock_no_getsockopt,
+#ifdef CONFIG_COMPAT
+	.compat_setsockopt	= sock_no_setsockopt,
+	.compat_getsockopt	= sock_no_getsockopt,
+#endif
+	.sendmsg		= msm_ipc_router_sendmsg,
+	.recvmsg		= msm_ipc_router_recvmsg,
+	.mmap			= sock_no_mmap,
+	.sendpage		= sock_no_sendpage,
+};
+
+static struct proto msm_ipc_proto = {
+	.name           = "MSM_IPC",
+	.owner          = THIS_MODULE,
+	.obj_size       = sizeof(struct msm_ipc_sock),
+};
+
+int msm_ipc_router_init_sockets(void)
+{
+	int ret;
+
+	ret = proto_register(&msm_ipc_proto, 1);
+	if (ret) {
+		IPC_RTR_ERR("%s: Failed to register MSM_IPC protocol type\n",
+			    __func__);
+		goto out_init_sockets;
+	}
+
+	ret = sock_register(&msm_ipc_family_ops);
+	if (ret) {
+		IPC_RTR_ERR("%s: Failed to register MSM_IPC socket type\n",
+			    __func__);
+		proto_unregister(&msm_ipc_proto);
+		goto out_init_sockets;
+	}
+
+	mutex_lock(&ipcrtr_af_init_lock);
+	sockets_enabled = 1;
+	raw_notifier_call_chain(&ipcrtr_af_init_chain,
+				IPCRTR_AF_INIT, NULL);
+	mutex_unlock(&ipcrtr_af_init_lock);
+out_init_sockets:
+	return ret;
+}
+
+void msm_ipc_router_exit_sockets(void)
+{
+	if (!sockets_enabled)
+		return;
+
+	sock_unregister(msm_ipc_family_ops.family);
+	proto_unregister(&msm_ipc_proto);
+	mutex_lock(&ipcrtr_af_init_lock);
+	sockets_enabled = 0;
+	raw_notifier_call_chain(&ipcrtr_af_init_chain,
+				IPCRTR_AF_DEINIT, NULL);
+	mutex_unlock(&ipcrtr_af_init_lock);
+}