blob: c5491bc050c367524872b03e2e9a8d038dd4e602 [file] [log] [blame]
/*
* 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);