msm: ipc: Load default subsystem under appropriate scenario

Only client and service ports are used for communication with the remote
subsystems. Load the default subsystem only when the clients lookup their
services or when the local services get registered with the IPC Router.

Change-Id: I18729bb849c656a826de4f67f9ffe159dd3cf5f6
Signed-off-by: Karthikeyan Ramasubramanian <kramasub@codeaurora.org>
diff --git a/arch/arm/mach-msm/ipc_router.h b/arch/arm/mach-msm/ipc_router.h
index 502cac1..32832dd 100644
--- a/arch/arm/mach-msm/ipc_router.h
+++ b/arch/arm/mach-msm/ipc_router.h
@@ -107,6 +107,7 @@
 struct msm_ipc_sock {
 	struct sock sk;
 	struct msm_ipc_port *port;
+	void *default_pil;
 };
 
 struct msm_ipc_router_xprt {
@@ -158,4 +159,15 @@
 
 void msm_ipc_sync_default_sec_rule(void *rule);
 
+#if defined CONFIG_MSM_IPC_ROUTER_SMD_XPRT
+extern void *msm_ipc_load_default_node(void);
+
+extern void msm_ipc_unload_default_node(void *pil);
+#else
+static inline void *msm_ipc_load_default_node(void)
+{ return NULL; }
+
+static inline void msm_ipc_unload_default_node(void *pil) { }
+#endif
+
 #endif
diff --git a/arch/arm/mach-msm/ipc_router_smd_xprt.c b/arch/arm/mach-msm/ipc_router_smd_xprt.c
index c7c2298..b2ec816 100644
--- a/arch/arm/mach-msm/ipc_router_smd_xprt.c
+++ b/arch/arm/mach-msm/ipc_router_smd_xprt.c
@@ -475,6 +475,31 @@
 	return 0;
 }
 
+void *msm_ipc_load_default_node(void)
+{
+	void *pil = NULL;
+	const char *peripheral;
+
+	peripheral = smd_edge_to_subsystem(SMD_APPS_MODEM);
+	if (peripheral && !strncmp(peripheral, "modem", 6)) {
+		pil = subsystem_get(peripheral);
+		if (IS_ERR(pil)) {
+			pr_err("%s: Failed to load %s\n",
+				__func__, peripheral);
+			pil = NULL;
+		}
+	}
+	return pil;
+}
+EXPORT_SYMBOL(msm_ipc_load_default_node);
+
+void msm_ipc_unload_default_node(void *pil)
+{
+	if (pil)
+		subsystem_put(pil);
+}
+EXPORT_SYMBOL(msm_ipc_unload_default_node);
+
 static struct platform_driver msm_ipc_router_smd_remote_driver[] = {
 	{
 		.probe		= msm_ipc_router_smd_remote_probe,
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index 3409867..515dc92 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.c
@@ -312,6 +312,7 @@
 	struct sock *sk = sock->sk;
 	struct msm_ipc_port *port_ptr;
 	int ret;
+	void *pil;
 
 	if (!sk)
 		return -EINVAL;
@@ -341,6 +342,8 @@
 	if (!port_ptr)
 		return -ENODEV;
 
+	pil = msm_ipc_load_default_node();
+	msm_ipc_sk(sk)->default_pil = pil;
 	lock_sock(sk);
 
 	ret = msm_ipc_router_register_server(port_ptr, &addr->address);
@@ -462,6 +465,7 @@
 	unsigned int n;
 	size_t srv_info_sz = 0;
 	int ret;
+	void *pil;
 
 	if (!sk)
 		return -EINVAL;
@@ -489,6 +493,8 @@
 		break;
 
 	case IPC_ROUTER_IOCTL_LOOKUP_SERVER:
+		pil = msm_ipc_load_default_node();
+		msm_ipc_sk(sk)->default_pil = pil;
 		ret = copy_from_user(&server_arg, (void *)arg,
 				     sizeof(server_arg));
 		if (ret) {
@@ -582,10 +588,13 @@
 {
 	struct sock *sk = sock->sk;
 	struct msm_ipc_port *port_ptr = msm_ipc_sk_port(sk);
+	void *pil = msm_ipc_sk(sk)->default_pil;
 	int ret;
 
 	lock_sock(sk);
 	ret = msm_ipc_router_close_port(port_ptr);
+	if (pil)
+		msm_ipc_unload_default_node(pil);
 	release_sock(sk);
 	sock_put(sk);
 	sock->sk = NULL;