#include #include #include #include #include #include #include #include #include #include "nt_smc_call.h" #include "utdriver_macro.h" #include "sched_status.h" #define CAPI_CALL 0x01 #define FDRV_CALL 0x02 #define BDRV_CALL 0x03 #define SCHED_CALL 0x04 #define FP_SYS_NO 100 #define VFS_SYS_NO 0x08 #define REETIME_SYS_NO 0x07 #define printk(fmt, args...) printk("\033[;34m[TEEI][TZDriver][switch_fn]"fmt"\033[0m", ##args) struct switch_head_struct { struct list_head head; }; struct switch_call_struct { int switch_type; unsigned long buff_addr; }; static void switch_fn(struct kthread_work *work); struct smc_call_struct { unsigned long local_cmd; u32 teei_cmd_type; u32 dev_file_id; u32 svc_id; u32 cmd_id; u32 context; u32 enc_id; void *cmd_buf; size_t cmd_len; void *resp_buf; size_t resp_len; void *meta_data; void *info_data; size_t info_len; int *ret_resp_len; int *error_code; struct semaphore *psema; int retVal; }; extern struct kthread_worker ut_fastcall_worker; extern int forward_call_flag; extern int fp_call_flag; extern int teei_vfs_flag; extern int irq_call_flag; extern void nt_sched_t_call(void); extern int __send_fp_command(unsigned long share_memory_size); extern int __vfs_handle(struct service_handler *handler); extern int __reetime_handle(struct service_handler *handler); extern int __teei_smc_call(unsigned long local_smc_cmd, u32 teei_cmd_type, u32 dev_file_id, u32 svc_id, u32 cmd_id, u32 context, u32 enc_id, const void *cmd_buf, size_t cmd_len, void *resp_buf, size_t resp_len, const void *meta_data, const void *info_data, size_t info_len, int *ret_resp_len, int *error_code, struct semaphore *psema); static struct switch_call_struct *create_switch_call_struct(void) { struct switch_call_struct *tmp_entry = NULL; tmp_entry = kmalloc(sizeof(struct switch_call_struct), GFP_KERNEL); if (tmp_entry == NULL) printk("[%s][%d] kmalloc failed!!!\n", __func__, __LINE__); return tmp_entry; } static int init_switch_call_struct(struct switch_call_struct *ent, int work_type, unsigned long buff) { if ((ent == NULL)) { printk("[%s][%d] the paraments are wrong!\n", __func__, __LINE__); return -EINVAL; } ent->switch_type = work_type; ent->buff_addr = buff; return 0; } static int destroy_switch_call_struct(struct switch_call_struct *ent) { kfree(ent); return 0; } struct ut_smc_call_work { struct kthread_work work; void *data; }; static int ut_smc_call(void *buff) { struct ut_smc_call_work usc_work = { KTHREAD_WORK_INIT(usc_work.work, switch_fn), .data = buff, }; if (!queue_kthread_work(&ut_fastcall_worker, &usc_work.work)) return -1; flush_kthread_work(&usc_work.work); return 0; } static int check_work_type(int work_type) { switch(work_type) { case CAPI_CALL: case FDRV_CALL: case BDRV_CALL: case SCHED_CALL: return 0; default: return -EINVAL; } } int add_work_entry(int work_type, unsigned long buff) { struct switch_call_struct *work_entry = NULL; int retVal = 0; retVal = check_work_type(work_type); if (retVal != 0) { printk("[%s][%d] with wrong work_type!\n", __func__, __LINE__); return retVal; } work_entry = create_switch_call_struct(); if (work_entry == NULL) { printk("[%s][%d] There is no enough memory!\n", __func__, __LINE__); return -ENOMEM; } retVal = init_switch_call_struct(work_entry, work_type, buff); if (retVal != 0) { printk("[%s][%d] init_switch_call_struct failed!\n", __func__, __LINE__); destroy_switch_call_struct(work_entry); return retVal; } #if 0 retVal = add_switch_call_link(&switch_queue_head, work_entry); #else retVal = ut_smc_call((void *)work_entry); #endif return retVal; } #if 0 int del_work_entry(struct switch_call_struct *ent) { int retVal = 0; retVal = del_switch_call_link(ent); if (retVal != 0) { printk("[%s][%d] del_switch_call_link failed %d!\n", __func__, __LINE__, retVal); return retVal; } retVal = destroy_switch_call_struct(ent); if (retVal != 0) { printk("[%s][%d] destroy_switch_call_struct failed %d!\n", __func__, __LINE__, retVal); return retVal; } return 0; } #endif int get_call_type(struct switch_call_struct *ent) { if (ent == NULL) return -EINVAL; return ent->switch_type; } int handle_sched_call(void *buff) { nt_sched_t(); return 0; } int handle_capi_call(void *buff) { struct smc_call_struct *cd = NULL; cd = (struct smc_call_struct *)buff; /* with a rmb() */ rmb(); cd->retVal = __teei_smc_call(cd->local_cmd, cd->teei_cmd_type, cd->dev_file_id, cd->svc_id, cd->cmd_id, cd->context, cd->enc_id, cd->cmd_buf, cd->cmd_len, cd->resp_buf, cd->resp_len, cd->meta_data, cd->info_data, cd->info_len, cd->ret_resp_len, cd->error_code, cd->psema); /* with a wmb() */ wmb(); return 0; } struct fdrv_call_struct { int fdrv_call_type; int fdrv_call_buff_size; int retVal; }; int handle_fdrv_call(void *buff) { struct fdrv_call_struct *cd = NULL; cd = (struct fdrv_call_struct *)buff; /* with a rmb() */ rmb(); switch(cd->fdrv_call_type) { case FP_SYS_NO: cd->retVal = __send_fp_command(cd->fdrv_call_buff_size); break; default: cd->retVal = -EINVAL; } /* with a wmb() */ wmb(); return 0; } struct bdrv_call_struct { int bdrv_call_type; struct service_handler *handler; int retVal; }; int handle_bdrv_call(void *buff) { struct bdrv_call_struct *cd = NULL; cd = (struct bdrv_call_struct *)buff; /* with a rmb() */ rmb(); switch(cd->bdrv_call_type) { case VFS_SYS_NO: cd->retVal = __vfs_handle(cd->handler); kfree(buff); break; case REETIME_SYS_NO: cd->retVal = __reetime_handle(cd->handler); kfree(buff); break; default: cd->retVal = -EINVAL; } /* with a wmb() */ wmb(); return 0; } int handle_switch_call(void *buff) { #if 0 if (forward_call_flag == GLSCH_FOR_SOTER) { forward_call_flag = GLSCH_NONE; msleep(10); nt_sched_t_call(); } else if (irq_call_flag == GLSCH_HIGH) { printk("[%s][%d]**************************\n", __func__, __LINE__ ); irq_call_flag = GLSCH_NONE; nt_sched_t_call(); /*msleep_interruptible(10);*/ } else if (fp_call_flag == GLSCH_HIGH) { printk("[%s][%d]**************************\n", __func__, __LINE__ ); if (teei_vfs_flag == 0) { nt_sched_t_call(); } else { msleep_interruptible(1); } } else if (forward_call_flag == GLSCH_LOW) { printk("[%s][%d]**************************\n", __func__, __LINE__ ); if (teei_vfs_flag == 0) { nt_sched_t_call(); } else { msleep_interruptible(1); } } else { printk("[%s][%d]**************************\n", __func__, __LINE__ ); msleep_interruptible(1); } #else nt_sched_t(); #endif } static void switch_fn(struct kthread_work *work) { struct ut_smc_call_work *switch_work = NULL; struct switch_call_struct *switch_ent = NULL; int call_type = 0; int retVal = 0; switch_work = container_of(work, struct ut_smc_call_work, work); switch_ent = (struct switch_call_struct *)switch_work->data; call_type = get_call_type(switch_ent); switch (call_type) { case CAPI_CALL: retVal = handle_capi_call(switch_ent->buff_addr); if (retVal < 0) { printk("[%s][%d] fail to handle ClientAPI!\n", __func__, __LINE__); } break; case FDRV_CALL: retVal = handle_fdrv_call(switch_ent->buff_addr); if (retVal < 0) { printk("[%s][%d] fail to handle F-driver!\n", __func__, __LINE__); } break; case BDRV_CALL: retVal = handle_bdrv_call(switch_ent->buff_addr); if (retVal < 0) { printk("[%s][%d] fail to handle B-driver!\n", __func__, __LINE__); } break; case SCHED_CALL: retVal = handle_sched_call(switch_ent->buff_addr); if (retVal < 0) { printk("[%s][%d] fail to handle sched-Call!\n", __func__, __LINE__); } break; default: printk("switch fn handles a undefined call! [%d] \n", call_type); } retVal = destroy_switch_call_struct(switch_ent); if (retVal != 0) { printk("[%s][%d] destroy_switch_call_struct failed %d!\n", __func__, __LINE__, retVal); return retVal; } return 0; }