| /* |
| * 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); |
| |