source: G950FXXS5DSI1
[GitHub/exynos8895/android_kernel_samsung_universal8895.git] / drivers / staging / sti / abc / abc_common.c
1 /* abc_common.c
2 *
3 * Abnormal Behavior Catcher Common Driver
4 *
5 * Copyright (C) 2017 Samsung Electronics
6 *
7 * Hyeokseon Yu <hyeokseon.yu@samsung.com>
8 *
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.
13 *
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.
18 *
19 */
20 #include <linux/sti/abc_common.h>
21
22 #define DEBUG_ABC
23 // #define ABC_WARNING_REPORT
24
25 static struct device *sec_abc;
26 static int abc_enabled;
27 static int abc_init;
28
29 #define ABC_PRINT(format, ...) pr_info("[sec_abc] " format, ##__VA_ARGS__)
30
31 #ifdef CONFIG_OF
32 static int parse_gpu_data(struct device *dev,
33 struct abc_platform_data *pdata,
34 struct device_node *np)
35 {
36 struct abc_qdata *cgpu;
37
38 cgpu = pdata->gpu_items;
39 cgpu->desc = of_get_property(np, "gpu,label", NULL);
40
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");
43 return -EINVAL;
44 }
45
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");
48 return -EINVAL;
49 }
50
51 cgpu->buffer.abc_element = kzalloc(sizeof(cgpu->buffer.abc_element[0]) * (cgpu->threshold_cnt + 1), GFP_KERNEL);
52
53 if (!cgpu->buffer.abc_element)
54 return -ENOMEM;
55
56 cgpu->buffer.size = cgpu->threshold_cnt + 1;
57 cgpu->buffer.rear = 0;
58 cgpu->buffer.front = 0;
59 cgpu->fail_cnt = 0;
60
61 return 0;
62 }
63
64 static int parse_aicl_data(struct device *dev,
65 struct abc_platform_data *pdata,
66 struct device_node *np)
67 {
68 struct abc_qdata *caicl;
69
70 caicl = pdata->aicl_items;
71 caicl->desc = of_get_property(np, "aicl,label", NULL);
72
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");
75 return -EINVAL;
76 }
77
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");
80 return -EINVAL;
81 }
82
83 caicl->buffer.abc_element = kzalloc(sizeof(caicl->buffer.abc_element[0]) *
84 (caicl->threshold_cnt + 1), GFP_KERNEL);
85
86 if (!caicl->buffer.abc_element)
87 return -ENOMEM;
88
89 caicl->buffer.size = caicl->threshold_cnt + 1;
90 caicl->buffer.rear = 0;
91 caicl->buffer.front = 0;
92 caicl->fail_cnt = 0;
93
94 return 0;
95 }
96
97 static int abc_parse_dt(struct device *dev)
98 {
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;
103
104 np = dev->of_node;
105 pdata->nItem = of_get_child_count(np);
106 if (!pdata->nItem) {
107 dev_err(dev, "There are no items\n");
108 return -ENODEV;
109 }
110
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);
115
116 if (!pdata->gpu_items) {
117 dev_err(dev, "Failed to allocate GPU memory\n");
118 return -ENOMEM;
119 }
120
121 if (gpu_np)
122 parse_gpu_data(dev, pdata, gpu_np);
123
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);
128
129 if (!pdata->aicl_items) {
130 dev_err(dev, "Failed to allocate AICL memory\n");
131 return -ENOMEM;
132 }
133
134 if (aicl_np)
135 parse_aicl_data(dev, pdata, aicl_np);
136
137 return 0;
138 }
139 #endif
140
141 #ifdef CONFIG_OF
142 static const struct of_device_id sec_abc_dt_match[] = {
143 { .compatible = "samsung,sec_abc" },
144 { }
145 };
146 #endif
147
148 static int sec_abc_resume(struct device *dev)
149 {
150 return 0;
151 }
152
153 static int sec_abc_remove(struct platform_device *pdev)
154 {
155 return 0;
156 }
157
158 static const struct dev_pm_ops sec_abc_pm = {
159 .resume = sec_abc_resume,
160 };
161
162 static void sec_abc_reset_gpu_buffer(void)
163 {
164 struct abc_info *pinfo = dev_get_drvdata(sec_abc);
165
166 pinfo->pdata->gpu_items->buffer.rear = 0;
167 pinfo->pdata->gpu_items->buffer.front = 0;
168 pinfo->pdata->gpu_items->fail_cnt = 0;
169 }
170
171 static void sec_abc_reset_aicl_buffer(void)
172 {
173 struct abc_info *pinfo = dev_get_drvdata(sec_abc);
174
175 pinfo->pdata->aicl_items->buffer.rear = 0;
176 pinfo->pdata->aicl_items->buffer.front = 0;
177 pinfo->pdata->aicl_items->fail_cnt = 0;
178 }
179
180 static ssize_t store_abc_enabled(struct device *dev,
181 struct device_attribute *attr,
182 const char *buf, size_t count)
183 {
184 struct abc_info *pinfo = dev_get_drvdata(sec_abc);
185
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();
199 }
200
201 abc_enabled = ABC_DISABLED;
202 }
203 return count;
204 }
205
206 static ssize_t show_abc_enabled(struct device *dev,
207 struct device_attribute *attr,
208 char *buf)
209 {
210 return sprintf(buf, "%d\n", abc_enabled);
211 }
212 static DEVICE_ATTR(enabled, 0644, show_abc_enabled, store_abc_enabled);
213
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)
218 {
219 struct abc_info *pinfo = dev_get_drvdata(sec_abc);
220 struct abc_log_entry *abc_log;
221
222 mutex_lock(&pinfo->log_mutex);
223
224 pinfo->log_list_cnt = 0;
225
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);
229 kfree(abc_log);
230 }
231
232 mutex_unlock(&pinfo->log_mutex);
233
234 return count;
235 }
236
237 /* read abc log_list */
238 static ssize_t show_abc_log(struct device *dev,
239 struct device_attribute *attr,
240 char *buf)
241 {
242 struct abc_info *pinfo = dev_get_drvdata(sec_abc);
243 struct abc_log_entry *abc_log;
244 int count = 0;
245
246 mutex_lock(&pinfo->log_mutex);
247
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);
250 }
251
252 mutex_unlock(&pinfo->log_mutex);
253
254 return count;
255 }
256 static DEVICE_ATTR(log, 0644, show_abc_log, store_abc_log);
257
258 static int sec_abc_is_full(struct abc_buffer *buffer)
259 {
260 if ((buffer->rear + 1) % buffer->size == buffer->front)
261 return 1;
262 else
263 return 0;
264 }
265
266 static int sec_abc_is_empty(struct abc_buffer *buffer)
267 {
268 if (buffer->front == buffer->rear)
269 return 1;
270 else
271 return 0;
272 }
273
274 static void sec_abc_enqueue(struct abc_buffer *buffer, struct abc_fault_info in)
275 {
276 if (sec_abc_is_full(buffer)) {
277 ABC_PRINT("queue is full.\n");
278 } else {
279 buffer->rear = (buffer->rear + 1) % buffer->size;
280 buffer->abc_element[buffer->rear] = in;
281 }
282 }
283
284 static void sec_abc_dequeue(struct abc_buffer *buffer, struct abc_fault_info *out)
285 {
286 if (sec_abc_is_empty(buffer)) {
287 ABC_PRINT("queue is empty.\n");
288 } else {
289 buffer->front = (buffer->front + 1) % buffer->size;
290 *out = buffer->abc_element[buffer->front];
291 }
292 }
293
294 static int sec_abc_get_diff_time(struct abc_buffer *buffer)
295 {
296 int front_time, rear_time;
297
298 front_time = buffer->abc_element[(buffer->front + 1) % buffer->size].cur_time;
299 rear_time = buffer->abc_element[buffer->rear].cur_time;
300
301 ABC_PRINT("front time : %d(%d) rear_time %d(%d) diff : %d\n",
302 front_time,
303 buffer->front + 1,
304 rear_time,
305 buffer->rear,
306 rear_time - front_time);
307
308 return rear_time - front_time;
309 }
310
311 int sec_abc_get_enabled(void)
312 {
313 return abc_enabled;
314 }
315 EXPORT_SYMBOL(sec_abc_get_enabled);
316
317 static void sec_abc_work_func(struct work_struct *work)
318 {
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;
323
324 struct timespec ts;
325 struct rtc_time tm;
326 unsigned long local_time;
327
328 char *c, *p;
329 char *uevent_str[ABC_UEVENT_MAX] = {0,};
330 char temp[ABC_BUFFER_MAX], timestamp[ABC_BUFFER_MAX], event_type[ABC_BUFFER_MAX];
331 int idx = 0;
332 u64 ktime;
333 unsigned long ktime_ms;
334 int ktime_rem;
335
336 strcpy(temp, pinfo->abc_str);
337 p = &temp[0];
338
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);
343
344 /* Caculate current local time */
345 getnstimeofday(&ts);
346 local_time = (u32)(ts.tv_sec - (sys_tz.tz_minuteswest * 60));
347 rtc_time_to_tm(local_time, &tm);
348
349 /* Parse uevent string */
350 while ((c = strsep(&p, "@")) != NULL) {
351 uevent_str[idx] = c;
352 idx++;
353 }
354 sprintf(timestamp, "TIMESTAMP=%lu", ktime_ms);
355 uevent_str[idx++] = &timestamp[0];
356 uevent_str[idx] = '\0';
357 strlcpy(event_type, uevent_str[1] + 6, sizeof(event_type));
358
359 ABC_PRINT("event type : %s\n", event_type);
360
361 #if defined(DEBUG_ABC)
362 idx = 0;
363 while ((c = uevent_str[idx]) != '\0') {
364 ABC_PRINT("%s\n", uevent_str[idx]);
365 idx++;
366 }
367 #endif
368
369 /* Add abc log_list */
370 mutex_lock(&pinfo->log_mutex);
371
372 abc_log = kzalloc(sizeof(*abc_log), GFP_KERNEL);
373 if (abc_log) {
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++;
380 } else {
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);
384 kfree(abc_log);
385 }
386 } else {
387 ABC_PRINT("failed to allocate abc_log\n");
388 }
389
390 mutex_unlock(&pinfo->log_mutex);
391
392 if (abc_enabled == ABC_TYPE1_ENABLED) {
393 pgpu = pinfo->pdata->gpu_items;
394 paicl = pinfo->pdata->aicl_items;
395
396 /* GPU fault */
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++;
400
401 ABC_PRINT("gpu fail count : %d\n", pgpu->fail_cnt);
402 sec_abc_enqueue(&pgpu->buffer, in);
403
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);
410 }
411 pgpu->fail_cnt = 0;
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);
419 }
420 sec_abc_dequeue(&pgpu->buffer, &out);
421 ABC_PRINT("cur_time : %lu cur_cnt : %d\n", out.cur_time, out.cur_cnt);
422 }
423
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);
428 #endif
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++;
432
433 ABC_PRINT("aicl fail count : %d\n", paicl->fail_cnt);
434 sec_abc_enqueue(&paicl->buffer, in);
435
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);
443 paicl->fail_cnt = 0;
444 } else {
445 paicl->fail_cnt--;
446 sec_abc_dequeue(&paicl->buffer, &out);
447 ABC_PRINT("cur_time : %lu cur_cnt : %d\n", out.cur_time, out.cur_cnt);
448 }
449 }
450 } else {
451 /* Others */
452 kobject_uevent_env(&sec_abc->kobj, KOBJ_CHANGE, uevent_str);
453 ABC_PRINT("Send uevent.\n");
454 }
455 } else { /* ABC_TYPE2_ENABLED */
456 kobject_uevent_env(&sec_abc->kobj, KOBJ_CHANGE, uevent_str);
457 ABC_PRINT("Send uevent.\n");
458 }
459 }
460
461 /* event string format
462 *
463 * ex) MODULE=tsp@ERROR=power_status_mismatch
464 * MODULE=tsp@ERROR=power_status_mismatch@EXT_LOG=fw_ver(0108)
465 *
466 */
467 void sec_abc_send_event(char *str)
468 {
469 struct abc_info *pinfo;
470
471 if (!abc_init) {
472 ABC_PRINT("ABC driver is not initialized!\n");
473 return;
474 }
475
476 if (abc_enabled == ABC_DISABLED) {
477 ABC_PRINT("ABC is disabled!\n");
478 return;
479 }
480
481 pinfo = dev_get_drvdata(sec_abc);
482
483 strlcpy(pinfo->abc_str, str, sizeof(pinfo->abc_str));
484 queue_work(pinfo->workqueue, &pinfo->work);
485 }
486 EXPORT_SYMBOL(sec_abc_send_event);
487
488 /**
489 * sec_abc_wait_enable() - wait for abc enable done
490 * Return : 0 for success, -1 for fail(timeout or abc not initialized)
491 */
492 int sec_abc_wait_enabled(void)
493 {
494 struct abc_info *pinfo;
495 unsigned long timeout;
496
497 if (!abc_init) {
498 ABC_PRINT("ABC driver is not initialized!\n");
499 return -1;
500 }
501
502 if (abc_enabled)
503 return 0;
504
505 pinfo = dev_get_drvdata(sec_abc);
506
507 reinit_completion(&pinfo->enable_done);
508
509 timeout = wait_for_completion_timeout(&pinfo->enable_done,
510 msecs_to_jiffies(ABC_WAIT_ENABLE_TIMEOUT));
511
512 if (timeout == 0) {
513 ABC_PRINT("%s : timeout!\n", __func__);
514 return -1;
515 }
516
517 return 0;
518 }
519 EXPORT_SYMBOL(sec_abc_wait_enabled);
520
521 static int sec_abc_probe(struct platform_device *pdev)
522 {
523 struct abc_platform_data *pdata;
524 struct abc_info *pinfo;
525 int ret = 0;
526
527 ABC_PRINT("%s\n", __func__);
528
529 abc_init = false;
530
531 if (pdev->dev.of_node) {
532 pdata = devm_kzalloc(&pdev->dev,
533 sizeof(struct abc_platform_data), GFP_KERNEL);
534
535 if (!pdata) {
536 dev_err(&pdev->dev, "Failed to allocate platform data\n");
537 return -ENOMEM;
538 }
539
540 pdev->dev.platform_data = pdata;
541 ret = abc_parse_dt(&pdev->dev);
542 if (ret) {
543 dev_err(&pdev->dev, "Failed to parse dt data\n");
544 return ret;
545 }
546
547 pr_info("%s: parse dt done\n", __func__);
548 } else {
549 pdata = pdev->dev.platform_data;
550 }
551
552 if (!pdata) {
553 dev_err(&pdev->dev, "There are no platform data\n");
554 return -EINVAL;
555 }
556
557 pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
558
559 if (!pinfo)
560 return -ENOMEM;
561
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__);
565 ret = -ENODEV;
566 goto out;
567 }
568
569 ret = device_create_file(pinfo->dev, &dev_attr_enabled);
570 if (ret) {
571 pr_err("%s: Failed to create device enabled file\n", __func__);
572 goto err_create_abc_enabled_sysfs;
573 }
574
575 ret = device_create_file(pinfo->dev, &dev_attr_log);
576 if (ret) {
577 pr_err("%s: Failed to create device log file\n", __func__);
578 goto err_create_abc_log_sysfs;
579 }
580
581 INIT_WORK(&pinfo->work, sec_abc_work_func);
582
583 pinfo->workqueue = create_singlethread_workqueue("sec_abc_wq");
584 if (!pinfo->workqueue)
585 goto err_create_abc_wq;
586
587 INIT_LIST_HEAD(&pinfo->log_list);
588 pinfo->log_list_cnt = 0;
589
590 init_completion(&pinfo->enable_done);
591
592 mutex_init(&pinfo->log_mutex);
593
594 sec_abc = pinfo->dev;
595 pinfo->pdata = pdata;
596
597 platform_set_drvdata(pdev, pinfo);
598
599 abc_init = true;
600 return ret;
601 err_create_abc_wq:
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);
607 out:
608 kfree(pinfo);
609 kfree(pdata);
610
611 return ret;
612 }
613
614 static struct platform_driver sec_abc_driver = {
615 .probe = sec_abc_probe,
616 .remove = sec_abc_remove,
617 .driver = {
618 .name = "sec_abc",
619 .owner = THIS_MODULE,
620 #if defined(CONFIG_PM)
621 .pm = &sec_abc_pm,
622 #endif
623 #if CONFIG_OF
624 .of_match_table = of_match_ptr(sec_abc_dt_match),
625 #endif
626 },
627 };
628
629 static int __init sec_abc_init(void)
630 {
631 ABC_PRINT("%s\n", __func__);
632
633 return platform_driver_register(&sec_abc_driver);
634 }
635
636 static void __exit sec_abc_exit(void)
637 {
638 return platform_driver_unregister(&sec_abc_driver);
639 }
640
641 module_init(sec_abc_init);
642 module_exit(sec_abc_exit);
643
644 MODULE_DESCRIPTION("Samsung ABC Driver");
645 MODULE_AUTHOR("Samsung Electronics");
646 MODULE_LICENSE("GPL");