3 * Abnormal Behavior Catcher Common Driver
5 * Copyright (C) 2017 Samsung Electronics
7 * Hyeokseon Yu <hyeokseon.yu@samsung.com>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
20 #include <linux/sti/abc_common.h>
23 // #define ABC_WARNING_REPORT
25 static struct device
*sec_abc
;
26 static int abc_enabled
;
29 #define ABC_PRINT(format, ...) pr_info("[sec_abc] " format, ##__VA_ARGS__)
32 static int parse_gpu_data(struct device
*dev
,
33 struct abc_platform_data
*pdata
,
34 struct device_node
*np
)
36 struct abc_qdata
*cgpu
;
38 cgpu
= pdata
->gpu_items
;
39 cgpu
->desc
= of_get_property(np
, "gpu,label", NULL
);
41 if (of_property_read_u32(np
, "gpu,threshold_count", &cgpu
->threshold_cnt
)) {
42 dev_err(dev
, "Failed to get gpu threshold count: node not exist\n");
46 if (of_property_read_u32(np
, "gpu,threshold_time", &cgpu
->threshold_time
)) {
47 dev_err(dev
, "Failed to get gpu threshold time: node not exist\n");
51 cgpu
->buffer
.abc_element
= kzalloc(sizeof(cgpu
->buffer
.abc_element
[0]) * (cgpu
->threshold_cnt
+ 1), GFP_KERNEL
);
53 if (!cgpu
->buffer
.abc_element
)
56 cgpu
->buffer
.size
= cgpu
->threshold_cnt
+ 1;
57 cgpu
->buffer
.rear
= 0;
58 cgpu
->buffer
.front
= 0;
64 static int parse_aicl_data(struct device
*dev
,
65 struct abc_platform_data
*pdata
,
66 struct device_node
*np
)
68 struct abc_qdata
*caicl
;
70 caicl
= pdata
->aicl_items
;
71 caicl
->desc
= of_get_property(np
, "aicl,label", NULL
);
73 if (of_property_read_u32(np
, "aicl,threshold_count", &caicl
->threshold_cnt
)) {
74 dev_err(dev
, "Failed to get aicl threshold count: node not exist\n");
78 if (of_property_read_u32(np
, "aicl,threshold_time", &caicl
->threshold_time
)) {
79 dev_err(dev
, "Failed to get aicl threshold time: node not exist\n");
83 caicl
->buffer
.abc_element
= kzalloc(sizeof(caicl
->buffer
.abc_element
[0]) *
84 (caicl
->threshold_cnt
+ 1), GFP_KERNEL
);
86 if (!caicl
->buffer
.abc_element
)
89 caicl
->buffer
.size
= caicl
->threshold_cnt
+ 1;
90 caicl
->buffer
.rear
= 0;
91 caicl
->buffer
.front
= 0;
97 static int abc_parse_dt(struct device
*dev
)
99 struct abc_platform_data
*pdata
= dev
->platform_data
;
100 struct device_node
*np
;
101 struct device_node
*gpu_np
;
102 struct device_node
*aicl_np
;
105 pdata
->nItem
= of_get_child_count(np
);
107 dev_err(dev
, "There are no items\n");
111 gpu_np
= of_find_node_by_name(np
, "gpu");
112 pdata
->nGpu
= of_get_child_count(gpu_np
);
113 pdata
->gpu_items
= devm_kzalloc(dev
,
114 sizeof(struct abc_qdata
), GFP_KERNEL
);
116 if (!pdata
->gpu_items
) {
117 dev_err(dev
, "Failed to allocate GPU memory\n");
122 parse_gpu_data(dev
, pdata
, gpu_np
);
124 aicl_np
= of_find_node_by_name(np
, "aicl");
125 pdata
->nAicl
= of_get_child_count(aicl_np
);
126 pdata
->aicl_items
= devm_kzalloc(dev
,
127 sizeof(struct abc_qdata
), GFP_KERNEL
);
129 if (!pdata
->aicl_items
) {
130 dev_err(dev
, "Failed to allocate AICL memory\n");
135 parse_aicl_data(dev
, pdata
, aicl_np
);
142 static const struct of_device_id sec_abc_dt_match
[] = {
143 { .compatible
= "samsung,sec_abc" },
148 static int sec_abc_resume(struct device
*dev
)
153 static int sec_abc_remove(struct platform_device
*pdev
)
158 static const struct dev_pm_ops sec_abc_pm
= {
159 .resume
= sec_abc_resume
,
162 static void sec_abc_reset_gpu_buffer(void)
164 struct abc_info
*pinfo
= dev_get_drvdata(sec_abc
);
166 pinfo
->pdata
->gpu_items
->buffer
.rear
= 0;
167 pinfo
->pdata
->gpu_items
->buffer
.front
= 0;
168 pinfo
->pdata
->gpu_items
->fail_cnt
= 0;
171 static void sec_abc_reset_aicl_buffer(void)
173 struct abc_info
*pinfo
= dev_get_drvdata(sec_abc
);
175 pinfo
->pdata
->aicl_items
->buffer
.rear
= 0;
176 pinfo
->pdata
->aicl_items
->buffer
.front
= 0;
177 pinfo
->pdata
->aicl_items
->fail_cnt
= 0;
180 static ssize_t
store_abc_enabled(struct device
*dev
,
181 struct device_attribute
*attr
,
182 const char *buf
, size_t count
)
184 struct abc_info
*pinfo
= dev_get_drvdata(sec_abc
);
186 if (!strncmp(buf
, "1", 1)) {
187 ABC_PRINT("ABC driver enabled.\n");
188 abc_enabled
= ABC_TYPE1_ENABLED
;
189 complete(&pinfo
->enable_done
);
190 } else if (!strncmp(buf
, "2", 1)) {
191 ABC_PRINT("Common driver enabled.\n");
192 abc_enabled
= ABC_TYPE2_ENABLED
;
193 complete(&pinfo
->enable_done
);
194 } else if (!strncmp(buf
, "0", 1)) {
195 ABC_PRINT("ABC/Common driver disabled.\n");
196 if (abc_enabled
== ABC_TYPE1_ENABLED
) {
197 sec_abc_reset_gpu_buffer();
198 sec_abc_reset_aicl_buffer();
201 abc_enabled
= ABC_DISABLED
;
206 static ssize_t
show_abc_enabled(struct device
*dev
,
207 struct device_attribute
*attr
,
210 return sprintf(buf
, "%d\n", abc_enabled
);
212 static DEVICE_ATTR(enabled
, 0644, show_abc_enabled
, store_abc_enabled
);
214 /* reset abc log_list */
215 static ssize_t
store_abc_log(struct device
*dev
,
216 struct device_attribute
*attr
,
217 const char *buf
, size_t count
)
219 struct abc_info
*pinfo
= dev_get_drvdata(sec_abc
);
220 struct abc_log_entry
*abc_log
;
222 mutex_lock(&pinfo
->log_mutex
);
224 pinfo
->log_list_cnt
= 0;
226 while (!list_empty(&pinfo
->log_list
)) {
227 abc_log
= list_first_entry(&pinfo
->log_list
, struct abc_log_entry
, node
);
228 list_del(&abc_log
->node
);
232 mutex_unlock(&pinfo
->log_mutex
);
237 /* read abc log_list */
238 static ssize_t
show_abc_log(struct device
*dev
,
239 struct device_attribute
*attr
,
242 struct abc_info
*pinfo
= dev_get_drvdata(sec_abc
);
243 struct abc_log_entry
*abc_log
;
246 mutex_lock(&pinfo
->log_mutex
);
248 list_for_each_entry(abc_log
, &pinfo
->log_list
, node
) {
249 count
+= snprintf(buf
+ count
, PAGE_SIZE
- count
, "%s\n", abc_log
->abc_log_str
);
252 mutex_unlock(&pinfo
->log_mutex
);
256 static DEVICE_ATTR(log
, 0644, show_abc_log
, store_abc_log
);
258 static int sec_abc_is_full(struct abc_buffer
*buffer
)
260 if ((buffer
->rear
+ 1) % buffer
->size
== buffer
->front
)
266 static int sec_abc_is_empty(struct abc_buffer
*buffer
)
268 if (buffer
->front
== buffer
->rear
)
274 static void sec_abc_enqueue(struct abc_buffer
*buffer
, struct abc_fault_info in
)
276 if (sec_abc_is_full(buffer
)) {
277 ABC_PRINT("queue is full.\n");
279 buffer
->rear
= (buffer
->rear
+ 1) % buffer
->size
;
280 buffer
->abc_element
[buffer
->rear
] = in
;
284 static void sec_abc_dequeue(struct abc_buffer
*buffer
, struct abc_fault_info
*out
)
286 if (sec_abc_is_empty(buffer
)) {
287 ABC_PRINT("queue is empty.\n");
289 buffer
->front
= (buffer
->front
+ 1) % buffer
->size
;
290 *out
= buffer
->abc_element
[buffer
->front
];
294 static int sec_abc_get_diff_time(struct abc_buffer
*buffer
)
296 int front_time
, rear_time
;
298 front_time
= buffer
->abc_element
[(buffer
->front
+ 1) % buffer
->size
].cur_time
;
299 rear_time
= buffer
->abc_element
[buffer
->rear
].cur_time
;
301 ABC_PRINT("front time : %d(%d) rear_time %d(%d) diff : %d\n",
306 rear_time
- front_time
);
308 return rear_time
- front_time
;
311 int sec_abc_get_enabled(void)
315 EXPORT_SYMBOL(sec_abc_get_enabled
);
317 static void sec_abc_work_func(struct work_struct
*work
)
319 struct abc_info
*pinfo
= container_of(work
, struct abc_info
, work
);
320 struct abc_qdata
*pgpu
, *paicl
;
321 struct abc_fault_info in
, out
;
322 struct abc_log_entry
*abc_log
;
326 unsigned long local_time
;
329 char *uevent_str
[ABC_UEVENT_MAX
] = {0,};
330 char temp
[ABC_BUFFER_MAX
], timestamp
[ABC_BUFFER_MAX
], event_type
[ABC_BUFFER_MAX
];
333 unsigned long ktime_ms
;
336 strcpy(temp
, pinfo
->abc_str
);
339 /* Caculate current kernel time */
340 ktime
= local_clock();
341 ktime_ms
= ktime
/ NSEC_PER_MSEC
;
342 ktime_rem
= do_div(ktime
, NSEC_PER_SEC
);
344 /* Caculate current local time */
346 local_time
= (u32
)(ts
.tv_sec
- (sys_tz
.tz_minuteswest
* 60));
347 rtc_time_to_tm(local_time
, &tm
);
349 /* Parse uevent string */
350 while ((c
= strsep(&p
, "@")) != NULL
) {
354 sprintf(timestamp
, "TIMESTAMP=%lu", ktime_ms
);
355 uevent_str
[idx
++] = ×tamp
[0];
356 uevent_str
[idx
] = '\0';
357 strlcpy(event_type
, uevent_str
[1] + 6, sizeof(event_type
));
359 ABC_PRINT("event type : %s\n", event_type
);
361 #if defined(DEBUG_ABC)
363 while ((c
= uevent_str
[idx
]) != '\0') {
364 ABC_PRINT("%s\n", uevent_str
[idx
]);
369 /* Add abc log_list */
370 mutex_lock(&pinfo
->log_mutex
);
372 abc_log
= kzalloc(sizeof(*abc_log
), GFP_KERNEL
);
374 snprintf(abc_log
->abc_log_str
, ABC_LOG_STR_LEN
, "[%5lu.%03d][%02d:%02d:%02d.%03lu]%s_%s",
375 (unsigned long)ktime
, (int)(ktime_rem
/ NSEC_PER_MSEC
), tm
.tm_hour
, tm
.tm_min
,
376 tm
.tm_sec
, ts
.tv_nsec
/ 1000000, uevent_str
[0] + 7, uevent_str
[1] + 6);
377 if (pinfo
->log_list_cnt
< ABC_LOG_MAX
) {
378 list_add_tail(&abc_log
->node
, &pinfo
->log_list
);
379 pinfo
->log_list_cnt
++;
381 list_add_tail(&abc_log
->node
, &pinfo
->log_list
);
382 abc_log
= list_first_entry(&pinfo
->log_list
, struct abc_log_entry
, node
);
383 list_del(&abc_log
->node
);
387 ABC_PRINT("failed to allocate abc_log\n");
390 mutex_unlock(&pinfo
->log_mutex
);
392 if (abc_enabled
== ABC_TYPE1_ENABLED
) {
393 pgpu
= pinfo
->pdata
->gpu_items
;
394 paicl
= pinfo
->pdata
->aicl_items
;
397 if (!strncasecmp(event_type
, "gpu_fault", 9)) {
398 in
.cur_time
= (unsigned long)ktime
/ USEC_PER_SEC
;
399 in
.cur_cnt
= pgpu
->fail_cnt
++;
401 ABC_PRINT("gpu fail count : %d\n", pgpu
->fail_cnt
);
402 sec_abc_enqueue(&pgpu
->buffer
, in
);
404 /* Check gpu fault */
405 /* Case 1 : Over threshold count */
406 if (pgpu
->fail_cnt
>= pgpu
->threshold_cnt
) {
407 if (sec_abc_get_diff_time(&pgpu
->buffer
) < pgpu
->threshold_time
) {
408 ABC_PRINT("GPU fault occurred. Send uevent.\n");
409 kobject_uevent_env(&sec_abc
->kobj
, KOBJ_CHANGE
, uevent_str
);
412 sec_abc_dequeue(&pgpu
->buffer
, &out
);
413 ABC_PRINT("cur_time : %lu cur_cnt : %d\n", out
.cur_time
, out
.cur_cnt
);
414 /* Case 2 : Check front and rear node in queue. Because it's occurred within max count */
415 } else if (sec_abc_is_full(&pgpu
->buffer
)) {
416 if (sec_abc_get_diff_time(&pgpu
->buffer
) < pgpu
->threshold_time
) {
417 ABC_PRINT("GPU fault occurred. Send uevent.\n");
418 kobject_uevent_env(&sec_abc
->kobj
, KOBJ_CHANGE
, uevent_str
);
420 sec_abc_dequeue(&pgpu
->buffer
, &out
);
421 ABC_PRINT("cur_time : %lu cur_cnt : %d\n", out
.cur_time
, out
.cur_cnt
);
424 #ifdef ABC_WARNING_REPORT
425 /* Send GPU fault warning */
426 strcat(uevent_str
[1], "_w");
427 kobject_uevent_env(&sec_abc
->kobj
, KOBJ_CHANGE
, uevent_str
);
429 } else if (!strncasecmp(event_type
, "aicl", 4)) { /* AICL fault */
430 in
.cur_time
= (unsigned long)ktime
/ USEC_PER_SEC
;
431 in
.cur_cnt
= paicl
->fail_cnt
++;
433 ABC_PRINT("aicl fail count : %d\n", paicl
->fail_cnt
);
434 sec_abc_enqueue(&paicl
->buffer
, in
);
436 /* Check aicl fault */
437 if (paicl
->fail_cnt
>= paicl
->threshold_cnt
) {
438 if (sec_abc_get_diff_time(&paicl
->buffer
) < paicl
->threshold_time
) {
439 ABC_PRINT("AICL fault occurred. Send uevent.\n");
440 kobject_uevent_env(&sec_abc
->kobj
, KOBJ_CHANGE
, uevent_str
);
441 while (!sec_abc_is_empty(&paicl
->buffer
))
442 sec_abc_dequeue(&paicl
->buffer
, &out
);
446 sec_abc_dequeue(&paicl
->buffer
, &out
);
447 ABC_PRINT("cur_time : %lu cur_cnt : %d\n", out
.cur_time
, out
.cur_cnt
);
452 kobject_uevent_env(&sec_abc
->kobj
, KOBJ_CHANGE
, uevent_str
);
453 ABC_PRINT("Send uevent.\n");
455 } else { /* ABC_TYPE2_ENABLED */
456 kobject_uevent_env(&sec_abc
->kobj
, KOBJ_CHANGE
, uevent_str
);
457 ABC_PRINT("Send uevent.\n");
461 /* event string format
463 * ex) MODULE=tsp@ERROR=power_status_mismatch
464 * MODULE=tsp@ERROR=power_status_mismatch@EXT_LOG=fw_ver(0108)
467 void sec_abc_send_event(char *str
)
469 struct abc_info
*pinfo
;
472 ABC_PRINT("ABC driver is not initialized!\n");
476 if (abc_enabled
== ABC_DISABLED
) {
477 ABC_PRINT("ABC is disabled!\n");
481 pinfo
= dev_get_drvdata(sec_abc
);
483 strlcpy(pinfo
->abc_str
, str
, sizeof(pinfo
->abc_str
));
484 queue_work(pinfo
->workqueue
, &pinfo
->work
);
486 EXPORT_SYMBOL(sec_abc_send_event
);
489 * sec_abc_wait_enable() - wait for abc enable done
490 * Return : 0 for success, -1 for fail(timeout or abc not initialized)
492 int sec_abc_wait_enabled(void)
494 struct abc_info
*pinfo
;
495 unsigned long timeout
;
498 ABC_PRINT("ABC driver is not initialized!\n");
505 pinfo
= dev_get_drvdata(sec_abc
);
507 reinit_completion(&pinfo
->enable_done
);
509 timeout
= wait_for_completion_timeout(&pinfo
->enable_done
,
510 msecs_to_jiffies(ABC_WAIT_ENABLE_TIMEOUT
));
513 ABC_PRINT("%s : timeout!\n", __func__
);
519 EXPORT_SYMBOL(sec_abc_wait_enabled
);
521 static int sec_abc_probe(struct platform_device
*pdev
)
523 struct abc_platform_data
*pdata
;
524 struct abc_info
*pinfo
;
527 ABC_PRINT("%s\n", __func__
);
531 if (pdev
->dev
.of_node
) {
532 pdata
= devm_kzalloc(&pdev
->dev
,
533 sizeof(struct abc_platform_data
), GFP_KERNEL
);
536 dev_err(&pdev
->dev
, "Failed to allocate platform data\n");
540 pdev
->dev
.platform_data
= pdata
;
541 ret
= abc_parse_dt(&pdev
->dev
);
543 dev_err(&pdev
->dev
, "Failed to parse dt data\n");
547 pr_info("%s: parse dt done\n", __func__
);
549 pdata
= pdev
->dev
.platform_data
;
553 dev_err(&pdev
->dev
, "There are no platform data\n");
557 pinfo
= kzalloc(sizeof(*pinfo
), GFP_KERNEL
);
562 pinfo
->dev
= sec_device_create(pinfo
, "sec_abc");
563 if (IS_ERR(pinfo
->dev
)) {
564 pr_err("%s Failed to create device(sec_abc)!\n", __func__
);
569 ret
= device_create_file(pinfo
->dev
, &dev_attr_enabled
);
571 pr_err("%s: Failed to create device enabled file\n", __func__
);
572 goto err_create_abc_enabled_sysfs
;
575 ret
= device_create_file(pinfo
->dev
, &dev_attr_log
);
577 pr_err("%s: Failed to create device log file\n", __func__
);
578 goto err_create_abc_log_sysfs
;
581 INIT_WORK(&pinfo
->work
, sec_abc_work_func
);
583 pinfo
->workqueue
= create_singlethread_workqueue("sec_abc_wq");
584 if (!pinfo
->workqueue
)
585 goto err_create_abc_wq
;
587 INIT_LIST_HEAD(&pinfo
->log_list
);
588 pinfo
->log_list_cnt
= 0;
590 init_completion(&pinfo
->enable_done
);
592 mutex_init(&pinfo
->log_mutex
);
594 sec_abc
= pinfo
->dev
;
595 pinfo
->pdata
= pdata
;
597 platform_set_drvdata(pdev
, pinfo
);
602 device_remove_file(pinfo
->dev
, &dev_attr_log
);
603 err_create_abc_log_sysfs
:
604 device_remove_file(pinfo
->dev
, &dev_attr_enabled
);
605 err_create_abc_enabled_sysfs
:
606 sec_device_destroy(sec_abc
->devt
);
614 static struct platform_driver sec_abc_driver
= {
615 .probe
= sec_abc_probe
,
616 .remove
= sec_abc_remove
,
619 .owner
= THIS_MODULE
,
620 #if defined(CONFIG_PM)
624 .of_match_table
= of_match_ptr(sec_abc_dt_match
),
629 static int __init
sec_abc_init(void)
631 ABC_PRINT("%s\n", __func__
);
633 return platform_driver_register(&sec_abc_driver
);
636 static void __exit
sec_abc_exit(void)
638 return platform_driver_unregister(&sec_abc_driver
);
641 module_init(sec_abc_init
);
642 module_exit(sec_abc_exit
);
644 MODULE_DESCRIPTION("Samsung ABC Driver");
645 MODULE_AUTHOR("Samsung Electronics");
646 MODULE_LICENSE("GPL");