Commit | Line | Data |
---|---|---|
6fa3eb70 S |
1 | #include <linux/kernel.h> |
2 | #include <linux/module.h> | |
3 | #include <linux/sysfs.h> | |
4 | #include <linux/device.h> | |
5 | #include <linux/uaccess.h> | |
6 | #include <linux/cdev.h> | |
7 | #include <linux/timer.h> | |
8 | #include <linux/timex.h> | |
9 | #include <linux/rtc.h> | |
10 | #include <linux/string.h> | |
11 | ||
12 | #include "eemcs_char.h" | |
13 | #include "eemcs_boot.h" | |
14 | #include "eemcs_debug.h" | |
15 | #include "eemcs_fs_ut.h" | |
16 | #include "eemcs_rpc_ut.h" | |
17 | #include "eemcs_statistics.h" | |
18 | #include "eemcs_state.h" | |
19 | #include "eemcs_expt_ut.h" | |
20 | ||
21 | extern EEMCS_BOOT_SET eemcs_boot_inst; | |
22 | ||
23 | /* | |
24 | * To show if "bypass CCCI handshake" is enabled | |
25 | */ | |
26 | static ssize_t eemcs_sysfs_show_ccci_hs_bypass(struct device *dev, struct device_attribute *attr, char *buf) | |
27 | { | |
28 | DBGLOG(SYSF, INF, "get CCCI handshake bypassed info: %d", eemcs_boot_inst.ccci_hs_bypass); | |
29 | return 0; | |
30 | } | |
31 | ||
32 | /* | |
33 | * To set "bypass CCCI handshake" flag | |
34 | */ | |
35 | static ssize_t eemcs_sysfs_set_ccci_hs_bypass(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | |
36 | { | |
37 | KAL_UINT32 bypass = 0; | |
38 | ||
39 | bypass = simple_strtol(buf, NULL, 10); | |
40 | if (bypass > 0) | |
41 | eemcs_boot_inst.ccci_hs_bypass = 1; | |
42 | else | |
43 | eemcs_boot_inst.ccci_hs_bypass = 0; | |
44 | DBGLOG(SYSF, INF, "set CCCI handshake bypassed info: %d", eemcs_boot_inst.ccci_hs_bypass); | |
45 | return count; | |
46 | } | |
47 | static DEVICE_ATTR(ccci_hs_bypass, S_IRUGO|S_IWUSR, eemcs_sysfs_show_ccci_hs_bypass, eemcs_sysfs_set_ccci_hs_bypass); | |
48 | ||
49 | #ifdef _EEMCS_FS_UT | |
50 | /* | |
51 | * To dump FS UT information | |
52 | */ | |
53 | static ssize_t eemcs_sysfs_show_fs_ut(struct device *dev, struct device_attribute *attr, char *buf) | |
54 | { | |
55 | eemcs_fs_ut_dump(); | |
56 | return 0; | |
57 | } | |
58 | ||
59 | /* | |
60 | * Use a positive value to trigger FS UT | |
61 | */ | |
62 | static ssize_t eemcs_sysfs_set_fs_ut(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | |
63 | { | |
64 | KAL_UINT32 go_ut = 0; | |
65 | ||
66 | go_ut = simple_strtol(buf, NULL, 10); | |
67 | if (go_ut >= 1) | |
68 | eemcs_fs_ut_trigger(); | |
69 | ||
70 | return count; | |
71 | } | |
72 | ||
73 | static DEVICE_ATTR(fs_ut, S_IRUGO|S_IWUSR, eemcs_sysfs_show_fs_ut, eemcs_sysfs_set_fs_ut); | |
74 | ||
75 | /* | |
76 | * To show the port index currently used in FS UT | |
77 | */ | |
78 | static ssize_t eemcs_sysfs_show_fs_ut_port(struct device *dev, struct device_attribute *attr, char *buf) | |
79 | { | |
80 | DBGLOG(SYSF, INF, "FS UT Get Port_idx=%d", eemcs_fs_ut_get_index()); | |
81 | return 0; | |
82 | } | |
83 | ||
84 | /* | |
85 | * To set the port index you want to use in FS UT | |
86 | */ | |
87 | static ssize_t eemcs_sysfs_set_fs_ut_port(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | |
88 | { | |
89 | KAL_UINT32 index = 0; | |
90 | ||
91 | index = simple_strtol(buf, NULL, 10); | |
92 | if (eemcs_fs_ut_set_index(index) >= 0) | |
93 | DBGLOG(SYSF, INF, "FS UT Set Port_idx=%d", index); | |
94 | else | |
95 | DBGLOG(SYSF, INF, "FS UT Set Port_idx=%d", index); | |
96 | ||
97 | return count; | |
98 | } | |
99 | static DEVICE_ATTR(fs_ut_port, S_IRUGO|S_IWUSR, eemcs_sysfs_show_fs_ut_port, eemcs_sysfs_set_fs_ut_port); | |
100 | ||
101 | #endif // _EEMCS_FS_UT | |
102 | ||
103 | ||
104 | #ifdef _EEMCS_RPC_UT | |
105 | ||
106 | /* | |
107 | * Use a positive value to trigger RPC UT | |
108 | */ | |
109 | static ssize_t eemcs_sysfs_set_rpc_ut(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | |
110 | { | |
111 | KAL_UINT32 go_ut = 0; | |
112 | ||
113 | go_ut = simple_strtol(buf, NULL, 10); | |
114 | if (go_ut >= 1) | |
115 | eemcs_rpc_ut_trigger(); | |
116 | ||
117 | return count; | |
118 | } | |
119 | static DEVICE_ATTR(rpc_ut, S_IRUGO|S_IWUSR, NULL, eemcs_sysfs_set_rpc_ut); | |
120 | ||
121 | ||
122 | #endif // _EEMCS_RPC_UT | |
123 | ||
124 | ||
125 | /* | |
126 | * Use 1 to print time of EMCSVA test start | |
127 | * 0 to print time of EMCSVA test stop | |
128 | */ | |
129 | static ssize_t eemcs_sysfs_emcsva_log(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | |
130 | { | |
131 | KAL_UINT32 emcsva_log_set = 0; | |
132 | struct timex txc; | |
133 | struct rtc_time tm; | |
134 | char c_time_string[30]={0}; | |
135 | do_gettimeofday(&(txc.time)); | |
136 | rtc_time_to_tm(txc.time.tv_sec,&tm); | |
137 | sprintf(c_time_string,"%04d-%02d-%02d_%02d:%02d:%02d",tm.tm_year+1900,tm.tm_mon+1, tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec); | |
138 | ||
139 | emcsva_log_set = simple_strtol(buf, NULL, 10); | |
140 | if (emcsva_log_set == 1){ | |
141 | DBGLOG(SYSF, INF, "++EEMCSVA Start: %s %s++", c_time_string, buf+2); | |
142 | } | |
143 | else if (emcsva_log_set == 0) { | |
144 | DBGLOG(SYSF, INF, "--EEMCSVA Stop : %s %s--", c_time_string, buf+2); | |
145 | } | |
146 | return count; | |
147 | } | |
148 | static DEVICE_ATTR(emcsva_log, S_IRUGO|S_IWUSR, NULL, eemcs_sysfs_emcsva_log); | |
149 | ||
150 | ||
151 | /* | |
152 | * To dump Boot restet test information | |
153 | */ | |
154 | extern unsigned char* g_md_sta_str[]; | |
155 | static ssize_t eemcs_show_boot_state(struct device *dev, struct device_attribute *attr, char *buf) | |
156 | { | |
157 | DBGLOG(SYSF, INF, "get md_boot_state=%s(%d)", g_md_sta_str[eemcs_boot_get_state()], eemcs_boot_get_state()); | |
158 | return sprintf(buf,"%d\n",eemcs_boot_get_state()); | |
159 | } | |
160 | ||
161 | /* | |
162 | * Use a positive value to trigger FS UT | |
163 | */ | |
164 | static ssize_t eemcs_set_boot_reset_state(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | |
165 | { | |
166 | KAL_UINT32 reset_state = 0; | |
167 | ||
168 | reset_state = simple_strtol(buf, NULL, 10); | |
169 | if (reset_state >= 0) | |
170 | DBGLOG(SYSF, INF, "set md_boot_state=%s(%d)", g_md_sta_str[reset_state], reset_state); | |
171 | eemcs_boot_reset_test(reset_state); | |
172 | ||
173 | return count; | |
174 | } | |
175 | ||
176 | static DEVICE_ATTR(boot_test, S_IRUGO|S_IWUSR, eemcs_show_boot_state, eemcs_set_boot_reset_state); | |
177 | ||
178 | /* | |
179 | * To show eemcs port statistics | |
180 | */ | |
181 | KAL_CHAR *ccci_port_name[CCCI_PORT_NUM_MAX]= | |
182 | { | |
183 | "eemcs_ctrl", | |
184 | "eemcs_sys", /* START_OF_NORMAL_PORT */ | |
185 | "eemcs_aud", | |
186 | "eemcs_meta", | |
187 | "eemcs_mux", | |
188 | "eemcs_fs", | |
189 | "eemcs_pmic", | |
190 | "eemcs_uem", | |
191 | "eemcs_rpc", | |
192 | "eemcs_ipc", | |
193 | "eemcs_ipc_uart", | |
194 | "eemcs_md_log", | |
195 | "eemcs_imsv", /* ims video */ | |
196 | "eemcs_imsc", /* ims control */ | |
197 | "eemcs_imsa", /* ims audio */ | |
198 | "eemcs_imsdc", /* ims data control */ | |
199 | "eemcs_muxrp", /* mux report channel, support ioctl only no i/o*/ | |
200 | "eemcs_ioctl", /* ioctl channel, support ioctl only no i/o*/ | |
201 | "eemcs_ril", /* rild channel, support ioctl only no i/o*/ | |
202 | "eemcs_it", /* END_OF_NORMAL_PORT-1 */ | |
203 | "ECCMNI1", | |
204 | "ECCMNI2", | |
205 | "ECCMNI3", | |
206 | }; | |
207 | static ssize_t eemcs_sysfs_show_statistics(struct device *dev, struct device_attribute *attr, char *buf) | |
208 | { | |
209 | int i = 0; | |
210 | char line[121]={0}; | |
211 | char c_time_string[30]={0}; | |
212 | int pos = 0; | |
213 | struct timeval tv; | |
214 | struct rtc_time tm; | |
215 | struct rtc_time tm_now; | |
216 | do_gettimeofday(&tv); | |
217 | rtc_time_to_tm(tv.tv_sec,&tm_now); | |
218 | rtc_time_to_tm(eemcs_statistics[0]->time.tv_sec,&tm); | |
219 | sprintf(c_time_string,"%04d-%02d-%02d_%02d:%02d:%02d ~ %02d:%02d - %d sec", | |
220 | tm.tm_year+1900,tm.tm_mon+1, tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec, | |
221 | tm_now.tm_min,tm_now.tm_sec, | |
222 | (unsigned int)(tv.tv_sec - eemcs_statistics[0]->time.tv_sec)); | |
223 | ||
224 | pos += sprintf(buf+pos, "Record Time: %s\n", c_time_string); | |
225 | ||
226 | pos += sprintf(buf+pos, "%15s | %7s | %7s | %9s | %8s | %8s | %7s | %7s |\n", | |
227 | "CCCI PORT", "TX CNT", "RX CNT", "RX Q(MAX)", "TX TOTAL", "RX TOTAL", "TX DROP", "RX DROP"); | |
228 | memset(line, '=', 91); | |
229 | pos += sprintf(buf+pos, "%s\n", line); | |
230 | for (i=0; i< CCCI_PORT_NUM_MAX; i++){ | |
231 | CCCI_PORT_STATISTICS *port = &eemcs_statistics[0]->port[i]; | |
232 | CCCI_PORT_STATISTICS *port_total = &eemcs_statistics[0]->port_total[i]; | |
233 | pos += sprintf(buf+pos, "%15s | %7d | %7d | %3d(%4d) | %8d | %8d | %7d | %7d |\n", | |
234 | ccci_port_name[i], port->cnt[TX], port->cnt[RX], | |
235 | port->queue[RX], port_total->queue[RX], | |
236 | port_total->cnt[TX], port_total->cnt[RX], | |
237 | port_total->drop[TX], port_total->drop[RX] | |
238 | ); | |
239 | } | |
240 | ||
241 | return pos; | |
242 | } | |
243 | ||
244 | /* | |
245 | * To set eemcs port statistics timer | |
246 | */ | |
247 | static ssize_t eemcs_sysfs_set_statistics(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | |
248 | { | |
249 | KAL_UINT32 input = 0; | |
250 | ||
251 | input = simple_strtol(buf, NULL, 10); | |
252 | ||
253 | switch(input){ | |
254 | case 0 : | |
255 | eemcs_statistics[0]->start = 0; | |
256 | break; | |
257 | ||
258 | default: | |
259 | eemcs_statistics[0]->inteval = input; | |
260 | eemcs_statistics[0]->start = 1; | |
261 | break; | |
262 | } | |
263 | ||
264 | return count; | |
265 | } | |
266 | static DEVICE_ATTR(eemcs_statistics, S_IRUGO|S_IWUSR, eemcs_sysfs_show_statistics, eemcs_sysfs_set_statistics); | |
267 | ||
268 | ||
269 | //=================================================================== | |
270 | // Exception Mode sysfs | |
271 | //=================================================================== | |
272 | ||
273 | #ifdef __EEMCS_EXPT_SUPPORT__ | |
274 | ||
275 | #define EEMCS_EX_MODE_LEN 16 | |
276 | ||
277 | /* | |
278 | * Show current exception mode (if in exception state) | |
279 | */ | |
280 | static ssize_t eemcs_sysfs_show_expt_mode(struct device *dev, struct device_attribute *attr, char *buf) | |
281 | { | |
282 | EEMCS_EXCEPTION_STATE mode = EEMCS_EX_INVALID; | |
283 | KAL_UINT32 is_exception; | |
284 | extern KAL_INT32 get_exception_mode(void); | |
285 | ||
286 | is_exception = is_exception_mode(&mode); | |
287 | mode = get_exception_mode(); | |
288 | return snprintf(buf, PAGE_SIZE, "[EXPT] %s in Exception and Exception Mode = 0x%X\n", (is_exception?"IS":"NOT"), mode); | |
289 | } | |
290 | ||
291 | #ifdef _EEMCS_EXCEPTION_UT | |
292 | ||
293 | /* | |
294 | * Set EEMCS to exception state | |
295 | * | |
296 | * "reset" ==> EEMCS_EX_INVALID = 0, | |
297 | * "none" ==> EEMCS_EX_NONE = 0, | |
298 | * "init" ==> EEMCS_EX_INIT = 1, | |
299 | * "dhl_ready" ==> EEMCS_EX_DHL_DL_RDY = 2, | |
300 | * "init_done" ==> EEMCS_EX_INIT_DONE = 3, | |
301 | */ | |
302 | static ssize_t eemcs_sysfs_set_expt_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | |
303 | { | |
304 | unsigned int ret = -EINVAL; | |
305 | char str_mode[EEMCS_EX_MODE_LEN] = {0}; | |
306 | EEMCS_EXCEPTION_STATE mode = EEMCS_EX_INVALID; | |
307 | KAL_UINT32 is_exception; | |
308 | DEBUG_LOG_FUNCTION_ENTRY; | |
309 | ||
310 | ret = sscanf(buf, "%15s", str_mode); | |
311 | if (ret != 1) | |
312 | return 0; | |
313 | DBGLOG(EXPT, INF, "exception mode command(%s), count=%d", str_mode, count); | |
314 | if (strnicmp(str_mode, "reset", EEMCS_EX_MODE_LEN) == 0) { | |
315 | change_device_state(EEMCS_INIT); | |
316 | } else if (strnicmp(str_mode, "none", EEMCS_EX_MODE_LEN) == 0) { | |
317 | set_exception_mode(EEMCS_EX_NONE); | |
318 | } else if (strnicmp(str_mode, "init", EEMCS_EX_MODE_LEN) == 0) { | |
319 | eemcs_expt_ut_trigger(EX_INIT); | |
320 | } else if (strnicmp(str_mode, "dhl_ready", EEMCS_EX_MODE_LEN) == 0) { | |
321 | eemcs_expt_ut_trigger(EX_DHL_DL_RDY); | |
322 | } else if (strnicmp(str_mode, "init_done", EEMCS_EX_MODE_LEN) == 0) { | |
323 | eemcs_expt_ut_trigger(EX_INIT_DONE); | |
324 | } else { | |
325 | DBGLOG(EXPT, WAR, "Nothing to do !!"); | |
326 | } | |
327 | is_exception = is_exception_mode(&mode); | |
328 | DBGLOG(SYSF, INF, "set Exception_Mode=%d when md %s in exception\n", (is_exception?"IS":"NOT"), mode); | |
329 | ||
330 | DEBUG_LOG_FUNCTION_LEAVE; | |
331 | return count; | |
332 | } | |
333 | static DEVICE_ATTR(expt_mode, S_IRUGO|S_IWUSR, eemcs_sysfs_show_expt_mode, eemcs_sysfs_set_expt_mode); | |
334 | #else // _EEMCS_EXCEPTION_UT | |
335 | static DEVICE_ATTR(expt_mode, S_IRUGO|S_IWUSR, eemcs_sysfs_show_expt_mode, NULL); | |
336 | #endif // _EEMCS_EXCEPTION_UT | |
337 | ||
338 | /* | |
339 | * Show exception mode statistics | |
340 | */ | |
341 | static ssize_t eemcs_sysfs_show_expt(struct device *dev, struct device_attribute *attr, char *buf) | |
342 | { | |
343 | return eemcs_expt_show_statistics(buf); | |
344 | } | |
345 | ||
346 | /* | |
347 | * Exception mode control | |
348 | */ | |
349 | static ssize_t eemcs_sysfs_set_expt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | |
350 | { | |
351 | unsigned int ret = -EINVAL; | |
352 | char ctrl_cmd[EEMCS_EX_MODE_LEN] = {0}; | |
353 | DEBUG_LOG_FUNCTION_ENTRY; | |
354 | ||
355 | ret = sscanf(buf, "%15s", ctrl_cmd); | |
356 | if (ret != 1) | |
357 | return 0; | |
358 | DBGLOG(SYSF, INF, "exception control command(%s), count=%d", ctrl_cmd, count); | |
359 | if (strnicmp(ctrl_cmd, "flush", EEMCS_EX_MODE_LEN) == 0) { | |
360 | eemcs_expt_flush(); | |
361 | } else { | |
362 | DBGLOG(SYSF, WAR, "[EXPT] Nothing to do!!"); | |
363 | } | |
364 | ||
365 | DEBUG_LOG_FUNCTION_LEAVE; | |
366 | return count; | |
367 | ||
368 | } | |
369 | static DEVICE_ATTR(expt, S_IRUGO|S_IWUSR, eemcs_sysfs_show_expt, eemcs_sysfs_set_expt); | |
370 | ||
371 | #ifdef _EEMCS_EXCEPTION_UT | |
372 | /* | |
373 | * Showing if loopback to CCCI in exception UT is enabled | |
374 | */ | |
375 | static ssize_t eemcs_sysfs_show_expt_ut_ccci_lb(struct device *dev, struct device_attribute *attr, char *buf) | |
376 | { | |
377 | return eemcs_expt_sysfs_show_ut_ccci_lb(buf); | |
378 | } | |
379 | ||
380 | /* | |
381 | * Disable/Enable loopback to CCCI in exception UT | |
382 | */ | |
383 | static ssize_t eemcs_sysfs_set_expt_ut_ccci_lb(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | |
384 | { | |
385 | KAL_UINT32 enable = 0; | |
386 | ||
387 | enable = simple_strtol(buf, NULL, 10); | |
388 | if (enable >= 1) | |
389 | eemcs_expt_enable_ut_ccci_lb(1); | |
390 | else | |
391 | eemcs_expt_enable_ut_ccci_lb(0); | |
392 | ||
393 | return count; | |
394 | } | |
395 | static DEVICE_ATTR(expt_ut_ccci_lb, S_IRUGO|S_IWUSR, eemcs_sysfs_show_expt_ut_ccci_lb, eemcs_sysfs_set_expt_ut_ccci_lb); | |
396 | ||
397 | #endif // _EEMCS_EXCEPTION_UT | |
398 | ||
399 | #endif // __EEMCS_EXPT_SUPPORT__ | |
400 | ||
401 | ||
402 | void eemcs_sysfs_init(struct class *dev_class) | |
403 | { | |
404 | struct device *dev = NULL; | |
405 | ||
406 | if (!IS_ERR(dev_class)) { | |
407 | dev = device_create(dev_class, NULL, MKDEV(EEMCS_DEV_MAJOR, END_OF_NORMAL_PORT), NULL, EEMCS_DEV_NAME); | |
408 | if (IS_ERR(dev)) { | |
409 | DBGLOG(SYSF, ERR, "create device(%s) fail", EEMCS_DEV_NAME); | |
410 | } else { | |
411 | if (device_create_file(dev, &dev_attr_ccci_hs_bypass) != 0) | |
412 | DBGLOG(SYSF, ERR, "create sysfs ccci_hs_bypass fail"); | |
413 | ||
414 | if (device_create_file(dev, &dev_attr_emcsva_log) != 0) | |
415 | DBGLOG(SYSF, ERR, "create sysfs emcsva_log fail"); | |
416 | ||
417 | if (device_create_file(dev, &dev_attr_boot_test) != 0) | |
418 | DBGLOG(SYSF, ERR, "create sysfs boot_test fail"); | |
419 | ||
420 | if (device_create_file(dev, &dev_attr_eemcs_statistics) != 0) | |
421 | DBGLOG(SYSF, ERR, "create sysfs eemcs_statistics fail"); | |
422 | #ifdef _EEMCS_RPC_UT | |
423 | if (device_create_file(dev, &dev_attr_rpc_ut) != 0) | |
424 | DBGLOG(SYSF, ERR, "create sysfs rpc_ut fail"); | |
425 | #endif // _EEMCS_RPC_UT | |
426 | ||
427 | #ifdef _EEMCS_FS_UT | |
428 | if (device_create_file(dev, &dev_attr_fs_ut) != 0) | |
429 | DBGLOG(SYSF, ERR, "create sysfs fs_ut fail"); | |
430 | if (device_create_file(dev, &dev_attr_fs_ut_port) != 0) | |
431 | DBGLOG(SYSF, ERR, "create sysfs fs_ut_port fail"); | |
432 | #endif // _EEMCS_FS_UT | |
433 | #ifdef __EEMCS_EXPT_SUPPORT__ | |
434 | if (device_create_file(dev, &dev_attr_expt_mode) != 0) | |
435 | DBGLOG(SYSF, ERR, "create sysfs expt_mode fail"); | |
436 | if (device_create_file(dev, &dev_attr_expt) != 0) | |
437 | DBGLOG(SYSF, ERR, "create sysfs expt_info fail"); | |
438 | #ifdef _EEMCS_EXCEPTION_UT | |
439 | if (device_create_file(dev, &dev_attr_expt_ut_ccci_lb) != 0) | |
440 | DBGLOG(SYSF, ERR, "create sysfs expt_ut_ccci_lb fail"); | |
441 | #endif // _EEMCS_EXCEPTION_UT | |
442 | #endif // __EEMCS_EXPT_SUPPORT__ | |
443 | ||
444 | ||
445 | } | |
446 | } | |
447 | } | |
448 | ||
449 | void eemcs_sysfs_exit(struct class *dev_class) | |
450 | { | |
451 | if (!IS_ERR(dev_class)) { | |
452 | device_destroy(dev_class, MKDEV(EEMCS_DEV_MAJOR, END_OF_NORMAL_PORT)); | |
453 | } | |
454 | } | |
455 |