| #include <linux/string.h> | |
| #include <linux/slab.h> | |
| #include <linux/kernel.h> | |
| #include "met_drv.h" | |
| #include "ondiemet_sspm.h" | |
| struct sspm_met_evnet_header { | |
| unsigned int rts_event_id; | |
| char *rts_event_name; | |
| char *chart_line_name; | |
| char *key_list; | |
| }; | |
| enum { | |
| #ifdef MET_SSPM_RTS_EVNET | |
| #undef MET_SSPM_RTS_EVNET | |
| #endif | |
| #define MET_SSPM_RTS_EVNET(rts_event_id, key_list) rts_event_id, | |
| #include "met_sspm_rts_event.h" | |
| /**********************/ | |
| CUR_MET_RTS_EVENT_NUM, | |
| MAX_MET_RTS_EVENT_NUM = 128 | |
| }; | |
| struct sspm_met_evnet_header met_evnet_header[MAX_MET_RTS_EVENT_NUM] = { | |
| #ifdef MET_SSPM_RTS_EVNET | |
| #undef MET_SSPM_RTS_EVNET | |
| #endif | |
| #define MET_SSPM_RTS_EVNET(rts_event_id, key_list) {rts_event_id, #rts_event_id, #rts_event_id, key_list}, | |
| #include "met_sspm_rts_event.h" | |
| }; | |
| static void ondiemet_sspm_start(void); | |
| static void ondiemet_sspm_stop(void); | |
| static int ondiemet_sspm_print_help(char *buf, int len); | |
| static int ondiemet_sspm_process_argument(const char *arg, int len); | |
| static int ondiemet_sspm_print_header(char *buf, int len); | |
| static unsigned int event_id_flag0; | |
| static unsigned int event_id_flag1; | |
| static unsigned int event_id_flag2; | |
| static unsigned int event_id_flag3; | |
| static char *update_rts_event_tbl[MAX_MET_RTS_EVENT_NUM]; | |
| static char sspm_help[] = " --sspm_common=rts_event_name\n"; | |
| static char header[] = "met-info [000] 0.0: sspm_common_header: "; | |
| struct metdevice met_sspm_common = { | |
| .name = "sspm_common", | |
| .owner = THIS_MODULE, | |
| .type = MET_TYPE_BUS, | |
| .cpu_related = 0, | |
| .ondiemet_mode = 1, | |
| .ondiemet_start = ondiemet_sspm_start, | |
| .ondiemet_stop = ondiemet_sspm_stop, | |
| .ondiemet_process_argument = ondiemet_sspm_process_argument, | |
| .ondiemet_print_help = ondiemet_sspm_print_help, | |
| .ondiemet_print_header = ondiemet_sspm_print_header, | |
| }; | |
| static int ondiemet_sspm_print_help(char *buf, int len) | |
| { | |
| return snprintf(buf, PAGE_SIZE, sspm_help); | |
| } | |
| static int ondiemet_sspm_print_header(char *buf, int len) | |
| { | |
| int i; | |
| int write_len; | |
| int flag = 0; | |
| static int is_dump_header = 0; | |
| static int read_idx = 0; | |
| len = 0; | |
| met_sspm_common.header_read_again = 0; | |
| if (is_dump_header == 0) { | |
| len = snprintf(buf, PAGE_SIZE, "%s", header); | |
| is_dump_header = 1; | |
| } | |
| for (i=read_idx; i<MAX_MET_RTS_EVENT_NUM; i++) { | |
| if (met_evnet_header[i].chart_line_name) { | |
| if (i <32) { | |
| flag = 1<<i; | |
| flag = event_id_flag0 & flag; | |
| } else if (i >=32 && i < 64) { | |
| flag = 1<<(i-32); | |
| flag = event_id_flag1 & flag; | |
| } else if (i >=64 && i < 96) { | |
| flag = 1<<(i-64); | |
| flag = event_id_flag2 & flag; | |
| } else if (i >=96 && i < 128) { | |
| flag = 1<<(i-96); | |
| flag = event_id_flag3 & flag; | |
| } | |
| if (flag == 0) | |
| continue; | |
| write_len = strlen(met_evnet_header[i].chart_line_name) + strlen(met_evnet_header[i].key_list) + 3; | |
| if ((len+write_len) < PAGE_SIZE) { | |
| len += snprintf(buf+len, PAGE_SIZE-len, "%u,%s,%s;", | |
| met_evnet_header[i].rts_event_id, | |
| met_evnet_header[i].chart_line_name, | |
| met_evnet_header[i].key_list); | |
| } else { | |
| met_sspm_common.header_read_again = 1; | |
| read_idx = i; | |
| return len; | |
| } | |
| } | |
| } | |
| if (i == MAX_MET_RTS_EVENT_NUM) { | |
| is_dump_header = 0; | |
| read_idx = 0; | |
| buf[len-1] = '\n'; | |
| for (i=0; i<MAX_MET_RTS_EVENT_NUM; i++) { | |
| if (update_rts_event_tbl[i]) { | |
| kfree(update_rts_event_tbl[i]); | |
| update_rts_event_tbl[i] = NULL; | |
| } | |
| } | |
| met_sspm_common.mode = 0; | |
| event_id_flag0 = 0; | |
| event_id_flag1 = 0; | |
| event_id_flag2 = 0; | |
| event_id_flag3 = 0; | |
| } | |
| return len; | |
| } | |
| static void ondiemet_sspm_start(void) | |
| { | |
| if (sspm_buf_available == 0) | |
| return ; | |
| /* ID_COMMON = 1<<MID_COMMON */ | |
| ondiemet_module[ONDIEMET_SSPM] |= ID_COMMON; | |
| } | |
| static void ondiemet_sspm_stop(void) | |
| { | |
| if (sspm_buf_available == 0) | |
| return ; | |
| } | |
| static void update_event_id_flag(int event_id) | |
| { | |
| unsigned int ipi_buf[4]; | |
| unsigned int rdata; | |
| unsigned int res; | |
| if (sspm_buf_available == 0) | |
| return ; | |
| /* main func ID: bit[31-24]; sub func ID: bit[23-18]; argu 0: bit[17-0] | |
| #define MET_MAIN_ID_MASK 0xff000000 | |
| #define FUNC_BIT_SHIFT 18 | |
| #define MET_ARGU (4 << FUNC_BIT_SHIFT) | |
| #define MID_BIT_SHIFT 9 | |
| */ | |
| if (event_id <32) { | |
| event_id_flag0 |= 1<<event_id; | |
| ipi_buf[0] = MET_MAIN_ID | MET_ARGU | MID_COMMON<<MID_BIT_SHIFT | 1; | |
| ipi_buf[1] = 0; | |
| ipi_buf[2] = event_id_flag0; | |
| ipi_buf[3] = 0; | |
| res = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1); | |
| } else if (event_id >=32 && event_id < 64) { | |
| event_id_flag1 |= 1<<(event_id-32); | |
| ipi_buf[0] = MET_MAIN_ID | MET_ARGU | MID_COMMON<<MID_BIT_SHIFT | 1; | |
| ipi_buf[1] = 1; | |
| ipi_buf[2] = event_id_flag1; | |
| ipi_buf[3] = 0; | |
| res = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1); | |
| } else if (event_id >=64 && event_id < 96) { | |
| event_id_flag2 |= 1<<(event_id-64); | |
| ipi_buf[0] = MET_MAIN_ID | MET_ARGU | MID_COMMON<<MID_BIT_SHIFT | 1; | |
| ipi_buf[1] = 2; | |
| ipi_buf[2] = event_id_flag2; | |
| ipi_buf[3] = 0; | |
| res = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1); | |
| } else if (event_id >=96 && event_id < 128) { | |
| event_id_flag3 = 1<<(event_id-96); | |
| ipi_buf[0] |= MET_MAIN_ID | MET_ARGU | MID_COMMON<<MID_BIT_SHIFT | 1; | |
| ipi_buf[1] = 3; | |
| ipi_buf[2] = event_id_flag3; | |
| ipi_buf[3] = 0; | |
| res = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1); | |
| } | |
| met_sspm_common.mode = 1; | |
| } | |
| static char *strdup(const char *s) | |
| { | |
| char *p = kmalloc(strlen(s) + 1, GFP_KERNEL); | |
| if (p) | |
| strcpy(p, s); | |
| return p; | |
| } | |
| static int ondiemet_sspm_process_argument(const char *arg, int len) | |
| { | |
| int i; | |
| int rts_event_id = -1; | |
| int res; | |
| char *line; | |
| char *token; | |
| for (i=0; met_evnet_header[i].rts_event_name && i<MAX_MET_RTS_EVENT_NUM; i++) { | |
| if (strcmp(met_evnet_header[i].rts_event_name, arg) == 0) { | |
| rts_event_id = i; | |
| break; | |
| } | |
| } | |
| if (strstarts(arg, "update_rts_event_tbl")) { | |
| char *ptr; | |
| /* update_rts_event_tbl=rts_event_id;rts_event_name;chart_line_name;key_list*/ | |
| line = strdup(arg); | |
| if (line == NULL) | |
| return -1; | |
| ptr = line; | |
| token = strsep(&line, "="); | |
| /* rts_event_id, */ | |
| token = strsep(&line, ";"); | |
| res = kstrtoint(token, 10, &rts_event_id); | |
| met_evnet_header[rts_event_id].rts_event_id = rts_event_id; | |
| /* rts_event_name */ | |
| token = strsep(&line, ";"); | |
| met_evnet_header[rts_event_id].rts_event_name = token; | |
| /* chart_line_name */ | |
| token = strsep(&line, ";"); | |
| met_evnet_header[rts_event_id].chart_line_name = token; | |
| /* key_list */ | |
| token = strsep(&line, ";\n"); | |
| met_evnet_header[rts_event_id].key_list = token; | |
| update_rts_event_tbl[rts_event_id] = ptr; | |
| } | |
| if (rts_event_id >=0) | |
| update_event_id_flag(rts_event_id); | |
| return 0; | |
| } | |
| EXPORT_SYMBOL(met_sspm_common); |