[Feature][ZXW-130]merge P50U02 version

Only Configure: No
Affected branch: master
Affected module: unknow
Is it affected on both ZXIC and MTK: only ZXIC
Self-test: Yes
Doc Update: No

Change-Id: I4f29ec5bb7c59385f23738d2b7ca84e67c100f69
diff --git a/ap/os/linux/linux-3.4.x/net/socket_rpmsg.c b/ap/os/linux/linux-3.4.x/net/socket_rpmsg.c
index 867b943..a42bfc2 100755
--- a/ap/os/linux/linux-3.4.x/net/socket_rpmsg.c
+++ b/ap/os/linux/linux-3.4.x/net/socket_rpmsg.c
@@ -6,6 +6,8 @@
 #include <net/af_unix.h>

 #include <linux/syscalls.h>

 #include <linux/file.h>

+#include <linux/debugfs.h>

+#include <linux/seq_file.h>

 //#include "ram_config.h"

 #include <linux/socket_rpmsg.h>

 

@@ -16,6 +18,8 @@
 #define sock_get_sema down_interruptible

 #define sock_put_sema up

 

+extern int socket_rpmsg_enable;

+

 struct sock_channel g_sock_chn_info;

 struct sock_rpmsg g_sock_rpmsg;

 struct ipc_socket *g_socket_ipc;

@@ -26,7 +30,7 @@
 struct hlist_head g_ipc_sockets;

 struct hlist_head g_sock_rpmsg_info;

 struct hlist_head g_sockets_info;

-	

+struct hlist_head g_sunaddr_info;	

 char* flag_value[] ={

 	"SOCK_DEAD",

 	"SOCK_DONE",

@@ -76,6 +80,9 @@
 DEFINE_SPINLOCK(sock_release_peer_lock);

 EXPORT_SYMBOL_GPL(sock_release_peer_lock);

 

+static struct dentry *ipcsocket_debugfs_dir_entry_root;

+static struct dentry *ipcsocket_debugfs_dir_entry_proc;

+

 #define unix_peer(sk) (unix_sk(sk)->peer)

 

 extern struct sock *unix_find_other_proxy(struct net *net,

@@ -96,6 +103,7 @@
 extern void unix_dgram_disconnected_proxy(struct sock *sk, struct sock *other);

 extern int unix_mkname_proxy(struct sockaddr_un *sunaddr, int len, unsigned *hashp);

 extern void unix_release_sock_proxy(struct sock *sk);

+extern void init_peercred_proxy(struct sock *sk);

 

 //static void delayed_release(struct work_struct *unused);

 int sock_soc_socket_is_valid(struct socket* proxysock, struct socket* localsock);

@@ -103,6 +111,23 @@
 

 static LIST_HEAD(delayed_release_list);

 

+#define DEFINE_SHOW_ATTRIBUTE(__name)					\

+static int __name##_open(struct inode *inode, struct file *file)	\

+{									\

+	return single_open(file, __name##_show, inode->i_private);	\

+}									\

+									\

+static const struct file_operations __name##_fops = {			\

+	.owner		= THIS_MODULE,					\

+	.open		= __name##_open,				\

+	.read		= seq_read,					\

+	.llseek		= seq_lseek,					\

+	.release	= single_release,				\

+}

+

+static int ipc_socket_info_show(struct seq_file *m, void *unused);

+DEFINE_SHOW_ATTRIBUTE(ipc_socket_info);

+

 enum sock_flags_cap {

 	SOCK_DEAD_CAP,

 	SOCK_DONE_CAP,

@@ -202,6 +227,32 @@
 	}

 }

 

+static int ipc_socket_info_show(struct seq_file *m, void *unused)

+{	

+	struct task_struct *task = NULL;

+	char taskname[TASK_COMM_LEN] = {0};

+	struct ipc_socket *p;

+	struct hlist_node *pos,*n;

+	struct socket* localsocket;	

+	

+	spin_lock(&sock_table_lock);

+	if(hlist_empty(&g_ipc_sockets))

+	{

+		sk_soc_warn("sock_print_ipc_socket_info  g_ipc_sockets is empty");

+		spin_unlock(&sock_table_lock);

+		return 0;

+	}

+	hlist_for_each_entry_safe(p, pos, n, &g_ipc_sockets, hlist_node) {

+		memset(taskname, 0, TASK_COMM_LEN);

+		localsocket = p->localsocket;

+		task = localsocket->task;

+		get_task_comm(taskname, task);	

+		sk_soc_warn("pid=%d, taskname=%s", task->pid, taskname);		

+	}

+	spin_unlock(&sock_table_lock);

+	return 0;

+}

+

 static int sock_soc_is_socket_peer(struct socket* socket, struct socket* peer)

 {

 	struct socket_info *p;

@@ -566,6 +617,68 @@
 	up(&psock_rpmsg_info->sock_sem);

 	return psock_rpmsg_info;

 }

+

+bool sock_soc_ipc_sunaddr_exist(struct sockaddr_un *psockaddr_un)

+{

+	struct sock_sunaddr_info *p;

+	struct hlist_node *pos,*n;

+	

+	hlist_for_each_entry_safe(p, pos, n, &g_sunaddr_info, hlist_node) {

+		if((p->sockaddr.sun_family == psockaddr_un->sun_family) \

+			&&(0 == memcmp(p->sockaddr.sun_path, psockaddr_un->sun_path, UNIX_PATH_MAX))){			

+						

+			return true;

+		}

+	}

+	

+	return false;

+}

+

+static void sock_soc_insert_ipc_sunaddr(struct sockaddr_un *psockaddr_un)

+{

+	struct sock_sunaddr_info *psock_sunaddr_info = NULL;

+

+	//ÏȲ鿴sunaddrÊÇ·ñÒѾ­ÔÚg_sunaddr_infoÖÐ

+	if(true == sock_soc_ipc_sunaddr_exist(psockaddr_un)){

+		sk_soc_info("sock_soc_insert_ipc_sunaddr, sunaddr already exist");

+		return;

+	}

+	

+	psock_sunaddr_info = (struct sock_sunaddr_info *)kzalloc(sizeof(struct sock_sunaddr_info), GFP_ATOMIC);

+	if(psock_sunaddr_info == NULL){

+		sk_soc_info("sock_soc_insert_ipc_sunaddr, alloc failed");

+		return;

+	}

+	memset(psock_sunaddr_info, 0, sizeof(struct sock_sunaddr_info));

+	memcpy(&psock_sunaddr_info->sockaddr, psockaddr_un, sizeof(struct sockaddr_un));	

+		

+	INIT_HLIST_NODE(&psock_sunaddr_info->hlist_node);

+	hlist_add_head(&psock_sunaddr_info->hlist_node, &g_sunaddr_info);	

+}

+

+static int sock_soc_del_ipc_sunaddr(struct sockaddr_un *psockaddr_un)

+{

+	struct sock_sunaddr_info *p;

+	struct hlist_node *pos,*n;

+	int ret;

+	hlist_for_each_entry_safe(p, pos, n, &g_sunaddr_info, hlist_node) {		

+		if(psockaddr_un->sun_path[0]){

+			ret = strncmp(p->sockaddr.sun_path, psockaddr_un->sun_path, strlen(psockaddr_un->sun_path));

+		}else{

+			ret = strncmp(&p->sockaddr.sun_path[1], &psockaddr_un->sun_path[1], strlen(&psockaddr_un->sun_path[1]));

+		}		

+		

+		if((p->sockaddr.sun_family == psockaddr_un->sun_family) && (0 == ret)){

+			hlist_del(&p->hlist_node);			

+			kfree(p);

+			sk_soc_info("sun_path=%s, del sucess.", psockaddr_un->sun_path);

+			return 0;

+		}

+	}

+	sk_soc_info("sun_path=%s, del failed", psockaddr_un->sun_path);

+	return -1;

+}

+

 int unix_is_ipc_socket(struct sock *sock)

 {

 	int result;

@@ -755,6 +868,18 @@
 	usock->rsock.remotesocket = remotesocket;

 }

 

+//±¾µØsocket¸üк󣬸üдúÀísocketÖÐrsockÐÅÏ¢

+void usock_update(struct sock* sock, int localfd, struct socket* localsocket)

+{

+	struct unix_sock* usock;

+	if(NULL == sock){

+		return;

+	}

+	usock = unix_sk(sock);

+	usock->rsock.localfd = localfd;

+	usock->rsock.localsocket = localsocket;

+}

+

 void usock_update_remote_proxy_socket(struct sock* sock, struct socket* remoteproxysocket)

 {

 	struct unix_sock* usock;

@@ -797,6 +922,7 @@
 		psocket_ipc->sock->sk_fd = psocket_ipc->sockfd;

 		//sock_soc_set_socket_info(psocket_ipc->socket, psock_rpmsg->clientsock);

 		sock_hold(psocket_ipc->sock); //0704

+		init_peercred_proxy(psocket_ipc->sock);

 		//³õʼ»¯´úÀísocketµÄusockÐÅÏ¢

 		usock_init(psocket_ipc->sock, psock_rpmsg->clientfd, psock_rpmsg->clientsock, psocket_ipc->sockfd, psocket_ipc->socket, psock_rpmsg->serverfd, psock_rpmsg->serversock);

 		usock_update_remote_proxy_socket(psocket_ipc->sock, psock_rpmsg->serverproxysock);

@@ -1087,7 +1213,7 @@
 		ipcsocket->localsocket = newsock;

 		sk_soc_info("remotesocket=%x, localsocket=%x", ipcsocket->remotesocket, ipcsocket->localsocket);

 	}else{

-		sk_soc_info("sock_soc_get_ipcsocket_by_proxysock failed, sock=%x", sock);

+		sk_soc_info("sock_soc_get_ipcsocket_by_proxysock failed, proxysock=%x, sock=%x", proxysock, sock);

 		return -1;

 	}

 	sk_soc_info("sock=%x, newsock=%x", sock, newsock);

@@ -1098,6 +1224,7 @@
 	sock_rpmsg.newsock = newsock;

 	sock_soc_del_socket_peer(sock, ipcsocket->proxysocket);

 	sock_soc_insert_socket_peer(newsock, ipcsocket->proxysocket);

+	usock_update(ipcsocket->sock, newsock->fd, newsock);

 	//newsock->peer = sock->peer; //0706

 	//sock->peer = NULL; //0706

 	sock_rpmsg.key = sock_rpmsg.serversock;

@@ -1918,14 +2045,19 @@
 {

 	struct ipc_socket* ipc_socket;

 	struct socket* serverproxysock;

-	ipc_socket = sock_soc_get_ipcsocket_by_proxysock(psock_rpmsg->serverproxysock);

+	serverproxysock = (struct socket*)psock_rpmsg->serverproxysock;

+	ipc_socket = sock_soc_get_ipcsocket_by_proxysock(serverproxysock->sk);

+	sk_soc_info("sock_soc_notify_proxy_change_to_server_proc serverproxysock=%x", psock_rpmsg->serverproxysock);

 	if(NULL != ipc_socket){

 		sk_soc_info("sock_soc_notify_proxy_change_to_server_proc remoteproxysocket=%x", psock_rpmsg->clientproxysock);

 		ipc_socket->remoteproxyfd = psock_rpmsg->clientproxyfd;

 		ipc_socket->remoteproxysocket = psock_rpmsg->clientproxysock;

 		serverproxysock = (struct socket*)psock_rpmsg->serverproxysock;

 		usock_update_remote_proxy_socket(serverproxysock->sk, psock_rpmsg->clientproxysock);

-	}	

+	}else{

+		sk_soc_info("sock_soc_notify_proxy_change_to_server_proc ipc_socket is NULL");

+	}

+	

 }

 

 struct sock *sock_soc_find_other(struct socket * socket/*int fd*/,

@@ -1936,6 +2068,15 @@
 	struct ipc_socket *psocket_ipc = NULL;

 	struct sock_rpmsg_info *psock_rpmsg_info = NULL;

 	int err;

+	

+	if(0 == socket_rpmsg_enable){

+		return NULL;

+	}	

+		

+	if(false == sock_soc_ipc_sunaddr_exist(sunname)){

+		sk_soc_info("sock_soc_ipc_sunaddr_exist is false, sunname=%s", sunname->sun_path);

+		return NULL; 

+	}

 	//struct socket *clisocket = sock_get_local_socket(fd, &err);

 	memcpy(&sock_rpmsg.sockaddr, sunname, sizeof(struct sockaddr_un));

 	sock_rpmsg.addr_len = len;

@@ -1952,6 +2093,10 @@
 	}

 	

 	psock_rpmsg_info = sock_soc_create_rpmsg_info(sock_rpmsg.key);

+	if(NULL == psock_rpmsg_info){

+		sk_soc_info("sock_soc_find_other create rpmsg faild \n");

+		return NULL;

+	}

 	sk_soc_info("sock_soc_find_other clientfd=%d, key=%x", sock_rpmsg.clientfd, sock_rpmsg.key);

 	sock_send_ipc_msg(&sock_rpmsg);

 	down_timeout(&psock_rpmsg_info->sock_sem, msecs_to_jiffies(g_sock_timeout));

@@ -2321,6 +2466,46 @@
 	return 0;

 }

 

+void sock_soc_unix_bind(struct sockaddr_un *sunaddr)

+{

+	struct ipc_socket *psocket_ipc = NULL;

+	struct sock_rpmsg sock_rpmsg = {0};

+	sock_rpmsg.msg_type = MSG_TYPE_UNIX_BIND;		

+	

+	memcpy(&sock_rpmsg.sockaddr, sunaddr, sizeof(struct sockaddr_un));

+	sk_soc_info("sock_soc_unix_bind  sunaddr=%s\n", sunaddr->sun_path);

+	sock_send_ipc_msg(&sock_rpmsg); 

+}

+

+int sock_soc_unix_bind_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct sockaddr_un sunaddr = {0};

+	memcpy(&sunaddr, &psock_rpmsg->sockaddr, sizeof(struct sockaddr_un));

+	sk_soc_info("sock_soc_unix_bind_proc  sunaddr=%s\n", sunaddr.sun_path);

+	sock_soc_insert_ipc_sunaddr(&sunaddr);

+	return 0;

+}

+

+void sock_soc_unix_unbind(struct sockaddr_un *sunaddr)

+{

+	struct ipc_socket *psocket_ipc = NULL;

+	struct sock_rpmsg sock_rpmsg = {0};

+	sock_rpmsg.msg_type = MSG_TYPE_UNIX_UNBIND;		

+	

+	memcpy(&sock_rpmsg.sockaddr, sunaddr, sizeof(struct sockaddr_un));

+	sk_soc_info("sock_soc_unix_unbind  sunaddr=%s\n", sunaddr->sun_path);

+	sock_send_ipc_msg(&sock_rpmsg); 

+}

+

+int sock_soc_unix_unbind_proc(struct sock_rpmsg* psock_rpmsg)

+{

+	struct sockaddr_un sunaddr = {0};

+	memcpy(&sunaddr, &psock_rpmsg->sockaddr, sizeof(struct sockaddr_un));

+	sk_soc_info("sock_soc_unix_unbind_proc  sunaddr=%s\n", sunaddr.sun_path);

+	sock_soc_del_ipc_sunaddr(&sunaddr);

+	return 0;

+}

+

 static int sock_create_icp_channel(T_ZDrvRpMsg_ActorID core_id, T_ZDrvRpMsg_ChID channel_id, unsigned int channel_size)

 {

     int retval;

@@ -2438,6 +2623,12 @@
 		case MSG_TYPE_NOTIFY_PROXY_CHANGE:

 			sock_soc_notify_proxy_change_to_server_proc(sock_rpmsg);

 			break;

+		case MSG_TYPE_UNIX_BIND:

+			sock_soc_unix_bind_proc(sock_rpmsg);

+			break;

+		case MSG_TYPE_UNIX_UNBIND:

+			sock_soc_unix_unbind_proc(sock_rpmsg);

+			break;

 		default:

 		    break;

 	}

@@ -2618,6 +2809,7 @@
 	INIT_HLIST_HEAD(&g_ipc_sockets);

 	INIT_HLIST_HEAD(&g_sock_rpmsg_info);

 	INIT_HLIST_HEAD(&g_sockets_info);

+	INIT_HLIST_HEAD(&g_sunaddr_info);

 	retval = sock_create_icp_channel(CAP_ID, ICP_CHN_SOCKET, ICP_CHANNEL_SIZE);

 	if(retval < 0) {

 		sk_soc_err("Create IcpChannel channel_32 fail.");

@@ -2643,7 +2835,19 @@
 		return PTR_ERR(th);

 	}

 	g_sock_chn_info.recv_thread_info.p_thread = th;

-	

+

+	ipcsocket_debugfs_dir_entry_root = debugfs_create_dir("ipc_socket", NULL);

+	if (ipcsocket_debugfs_dir_entry_root)

+		ipcsocket_debugfs_dir_entry_proc = debugfs_create_dir("proc",

+						 ipcsocket_debugfs_dir_entry_root);

+

+	if (ipcsocket_debugfs_dir_entry_root) {

+		debugfs_create_file("ipc_socket_info",

+				    0444,

+				    ipcsocket_debugfs_dir_entry_root,

+				    NULL,

+				    &ipc_socket_info_fops);

+	}

 	return 0;

 }