| /* | 
 |  * linux/ipc/cross_msg.c | 
 |  * Copyright (C) 2023 Sanechips Technology Co., Ltd. | 
 |  */ | 
 | #include <linux/kthread.h> | 
 | #include <linux/mm.h> | 
 | #include <linux/slab.h> | 
 | #include <asm/uaccess.h> | 
 |  | 
 | #include "cross_msg.h" | 
 |  | 
 | extern int msg_chn_ready; | 
 | extern struct mutex cross_msg_mutex; | 
 |  | 
 | extern int sys_msgget(key_t key, int msgflg); | 
 | extern long do_kmsgsnd(int msqid, struct msgbuf* msgp, size_t msgsz, int msgflg); | 
 |  | 
 | static void msg_ap_icp_init(void) | 
 | { | 
 | 	mutex_init(&cross_msg_mutex); | 
 |  | 
 | 	if (zDrvRpMsg_CreateChannel_Cap(CROSS_MSG_ACT, CROSS_MSG_CHN, CROSS_CHN_SIZE)) { | 
 | 		panic(CROSS_PRINT "Failed create ap->cap msg channel id %d!\n", CROSS_MSG_CHN); | 
 | 	} else { | 
 | 		printk(KERN_INFO CROSS_PRINT "create ap->cap msg channel success!\n"); | 
 | 		msg_chn_ready = 1; | 
 | 	} | 
 | 	 | 
 | 	if (zDrvRpMsg_CreateChannel_Cap(CROSS_MSG_ACT, CROSS_MSG_CHN_CAP, CROSS_CHN_SIZE)) { | 
 | 		panic(CROSS_PRINT "Failed create cap->ap msg channel id %d\n", CROSS_MSG_CHN_CAP); | 
 | 	} else { | 
 | 		printk(KERN_INFO CROSS_PRINT "create cap->ap msg channel success!\n"); | 
 | 	} | 
 | } | 
 |  | 
 | void cross_msg_recv() | 
 | { | 
 | 	T_sc_msg_header *msgheader = NULL; | 
 | 	long *typeheader = NULL; | 
 | 	char *textheader = NULL; | 
 | 	T_ZDrvRpMsg_Msg Icp_Msg; | 
 | 	int ret; | 
 | 	int msqid, alen; | 
 | 	 | 
 | 	msgheader = (T_sc_msg_header *)kmalloc(CROSS_MSG_SIZE, GFP_KERNEL); | 
 | 	if (!msgheader) { | 
 | 		panic(CROSS_PRINT "Failed malloc send msgheader!\n"); | 
 | 	} | 
 |  | 
 | 	while (1) | 
 | 	{ | 
 | 		memset(msgheader, 0, sizeof(T_sc_msg_header)); | 
 | 		Icp_Msg.actorID	= CROSS_MSG_ACT; | 
 | 		Icp_Msg.chID	= CROSS_MSG_CHN_CAP; | 
 | 		Icp_Msg.buf		= msgheader;  | 
 | 		Icp_Msg.len		= CROSS_MSG_SIZE; | 
 | 		Icp_Msg.flag	= 0; | 
 | 		ret = zDrvRpMsg_Read_Cap(&Icp_Msg); | 
 | #if CROSS_DEBUG  | 
 | 		printk(KERN_INFO CROSS_PRINT "cross message rpmsg recv header %x ops %x\n", msgheader->head, msgheader->ops); | 
 | #endif | 
 | 		if(ret < 0) { | 
 | 			printk(KERN_ERR CROSS_PRINT "read rmpsg from cap error:(%d)\n", ret); | 
 | 			continue; | 
 | 		} | 
 | 		if (msgheader->head != CROSS_MSG_HEAD) | 
 | 		{ | 
 | 			printk(KERN_ERR CROSS_PRINT "read rmpsg content error\n"); | 
 | 			continue; | 
 | 		} | 
 | 		switch (msgheader->ops) { | 
 | 			case MSGGET_F: { | 
 | 				break; | 
 | 			} | 
 | 			case MSGCTL_F: { | 
 | 				break; | 
 | 			} | 
 | 			case MSGSND_F: { | 
 | 				typeheader = (long *)(msgheader + 1); | 
 | 				textheader = (char *)(typeheader + 1); | 
 | #if CROSS_DEBUG  | 
 | 				printk(KERN_INFO CROSS_PRINT "cross message msgget key:(%d) flag:(%d)\n", msgheader->sndp.getp.key, msgheader->sndp.getp.msgflg); | 
 | #endif | 
 | 				msqid = sys_msgget(msgheader->sndp.getp.key, msgheader->sndp.getp.msgflg); | 
 | 				if (msqid < 0) { | 
 | 					printk(KERN_ERR CROSS_PRINT "msgget error:(%d)\n", msqid); | 
 | 					ret = msqid; | 
 | 					goto ack; | 
 | 				} | 
 | #if CROSS_DEBUG  | 
 | 				printk(KERN_INFO CROSS_PRINT "cross message msgsnd text:(%s) msgtyp:(%d)\n", textheader, *typeheader); | 
 | 				printk(KERN_INFO CROSS_PRINT "cross message msgsnd msgflg: %x, msgsz:(%d)\n", msgheader->sndp.msgflg, msgheader->sndp.msgsz); | 
 | #endif | 
 | 				ret = do_kmsgsnd(msqid, typeheader, msgheader->sndp.msgsz, msgheader->sndp.msgflg); | 
 | 				if (ret < 0) { | 
 | 					printk(KERN_ERR CROSS_PRINT "msgsnd error:(%d)\n", ret); | 
 | 					goto ack; | 
 | 				} | 
 | #if CROSS_DEBUG  | 
 | 				printk(KERN_INFO CROSS_PRINT "cross message msgsnd ret:(%d)\n", ret); | 
 | #endif | 
 | ack:		  | 
 | 				msgheader->head	= CROSS_MSG_HEAD; | 
 | 				msgheader->ret	= ret; | 
 | 				Icp_Msg.actorID	= CROSS_MSG_ACT; | 
 | 				Icp_Msg.chID	= CROSS_MSG_CHN_CAP; | 
 | 				Icp_Msg.flag	= RPMSG_WRITE_INT; | 
 | 				Icp_Msg.buf		= msgheader; | 
 | 				Icp_Msg.len		= sizeof(T_sc_msg_header); | 
 | 				ret = zDrvRpMsg_Write_Cap(&Icp_Msg); | 
 | 				if (ret < 0) | 
 | 					printk(KERN_INFO CROSS_PRINT "write rpmsg to cap error:(%d)\n", ret); | 
 | 				break; | 
 | 			} | 
 | 			case MSGRCV_F: { | 
 | 				break; | 
 | 			} | 
 | 			default: { | 
 | 				printk(KERN_INFO CROSS_PRINT "cross message msg options unknow:(%d)\n", ret); | 
 | 				break; | 
 | 			} | 
 | 		} | 
 | 	} | 
 | 	 | 
 | } | 
 |  | 
 | void __init cross_msg_init(void) | 
 | { | 
 | 	struct task_struct *recv_msg_thread;  | 
 | 	msg_ap_icp_init(); | 
 | 	 | 
 | 	printk(KERN_INFO CROSS_PRINT "cross message init"); | 
 | 	recv_msg_thread = kthread_run(cross_msg_recv, NULL, "cross_msg_recv"); | 
 | 	if (IS_ERR(recv_msg_thread)) { | 
 | 		panic("create recv_msg_thread err"); | 
 | 	} | 
 | 	else { | 
 | 		wake_up_process(recv_msg_thread);	   | 
 | 	} | 
 | } | 
 | late_initcall(cross_msg_init); | 
 |  |