8a54e73f64a071890d141001e334f19f9edbde05
[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 pinfo->log_list_cnt = 0;
223
224 while (!list_empty(&pinfo->log_list)) {
225 abc_log = list_first_entry(&pinfo->log_list, struct abc_log_entry, node);
226 list_del(&abc_log->node);
227 kfree(abc_log);
228 }
229
230 return count;
231 }
232
233 /* read abc log_list */
234 static ssize_t show_abc_log(struct device *dev,
235 struct device_attribute *attr,
236 char *buf)
237 {
238 struct abc_info *pinfo = dev_get_drvdata(sec_abc);
239 struct abc_log_entry *abc_log;
240 int count = 0;
241
242 list_for_each_entry(abc_log, &pinfo->log_list, node) {
243 count += sprintf(buf + count, "%s\n", abc_log->abc_log_str);
244 }
245
246 return count;
247 }
248 static DEVICE_ATTR(log, 0644, show_abc_log, store_abc_log);
249
250 static int sec_abc_is_full(struct abc_buffer *buffer)
251 {
252 if ((buffer->rear + 1) % buffer->size == buffer->front)
253 return 1;
254 else
255 return 0;
256 }
257
258 static int sec_abc_is_empty(struct abc_buffer *buffer)
259 {
260 if (buffer->front == buffer->rear)
261 return 1;
262 else
263 return 0;
264 }
265
266 static void sec_abc_enqueue(struct abc_buffer *buffer, struct abc_fault_info in)
267 {
268 if (sec_abc_is_full(buffer)) {
269 ABC_PRINT("queue is full.\n");
270 } else {
271 buffer->rear = (buffer->rear + 1) % buffer->size;
272 buffer->abc_element[buffer->rear] = in;
273 }
274 }
275
276 static void sec_abc_dequeue(struct abc_buffer *buffer, struct abc_fault_info *out)
277 {
278 if (sec_abc_is_empty(buffer)) {
279 ABC_PRINT("queue is empty.\n");
280 } else {
281 buffer->front = (buffer->front + 1) % buffer->size;
282 *out = buffer->abc_element[buffer->front];
283 }
284 }
285
286 static int sec_abc_get_diff_time(struct abc_buffer *buffer)
287 {
288 int front_time, rear_time;
289
290 front_time = buffer->abc_element[(buffer->front + 1) % buffer->size].cur_time;
291 rear_time = buffer->abc_element[buffer->rear].cur_time;
292
293 ABC_PRINT("front time : %d(%d) rear_time %d(%d) diff : %d\n",
294 front_time,
295 buffer->front + 1,
296 rear_time,
297 buffer->rear,
298 rear_time - front_time);
299
300 return rear_time - front_time;
301 }
302
303 int sec_abc_get_enabled(void)
304 {
305 return abc_enabled;
306 }
307 EXPORT_SYMBOL(sec_abc_get_enabled);
308
309 static void sec_abc_work_func(struct work_struct *work)
310 {
311 struct abc_info *pinfo = container_of(work, struct abc_info, work);
312 struct abc_qdata *pgpu, *paicl;
313 struct abc_fault_info in, out;
314 struct abc_log_entry *abc_log;
315
316 struct timespec ts;
317 struct rtc_time tm;
318 unsigned long local_time;
319
320 char *c, *p;
321 char *uevent_str[ABC_UEVENT_MAX] = {0,};
322 char temp[ABC_BUFFER_MAX], timestamp[ABC_BUFFER_MAX], event_type[ABC_BUFFER_MAX];
323 int idx = 0;
324 u64 ktime;
325 unsigned long ktime_ms;
326 int ktime_rem;
327
328 strcpy(temp, pinfo->abc_str);
329 p = &temp[0];
330
331 /* Caculate current kernel time */
332 ktime = local_clock();
333 ktime_ms = ktime / NSEC_PER_MSEC;
334 ktime_rem = do_div(ktime, NSEC_PER_SEC);
335
336 /* Caculate current local time */
337 getnstimeofday(&ts);
338 local_time = (u32)(ts.tv_sec - (sys_tz.tz_minuteswest * 60));
339 rtc_time_to_tm(local_time, &tm);
340
341 /* Parse uevent string */
342 while ((c = strsep(&p, "@")) != NULL) {
343 uevent_str[idx] = c;
344 idx++;
345 }
346 sprintf(timestamp, "TIMESTAMP=%lu", ktime_ms);
347 uevent_str[idx++] = &timestamp[0];
348 uevent_str[idx] = '\0';
349 strlcpy(event_type, uevent_str[1] + 6, sizeof(event_type));
350
351 ABC_PRINT("event type : %s\n", event_type);
352
353 #if defined(DEBUG_ABC)
354 idx = 0;
355 while ((c = uevent_str[idx]) != '\0') {
356 ABC_PRINT("%s\n", uevent_str[idx]);
357 idx++;
358 }
359 #endif
360
361 /* Add abc log_list */
362 abc_log = kzalloc(sizeof(*abc_log), GFP_KERNEL);
363 if (abc_log) {
364 snprintf(abc_log->abc_log_str, ABC_LOG_STR_LEN, "[%5lu.%03d][%02d:%02d:%02d.%03lu]%s_%s",
365 (unsigned long)ktime, (int)(ktime_rem / NSEC_PER_MSEC), tm.tm_hour, tm.tm_min,
366 tm.tm_sec, ts.tv_nsec / 1000000, uevent_str[0] + 7, uevent_str[1] + 6);
367 if (pinfo->log_list_cnt < ABC_LOG_MAX) {
368 list_add_tail(&abc_log->node, &pinfo->log_list);
369 pinfo->log_list_cnt++;
370 } else {
371 list_add_tail(&abc_log->node, &pinfo->log_list);
372 abc_log = list_first_entry(&pinfo->log_list, struct abc_log_entry, node);
373 list_del(&abc_log->node);
374 kfree(abc_log);
375 }
376 } else {
377 ABC_PRINT("failed to allocate abc_log\n");
378 }
379
380 if (abc_enabled == ABC_TYPE1_ENABLED) {
381 pgpu = pinfo->pdata->gpu_items;
382 paicl = pinfo->pdata->aicl_items;
383
384 /* GPU fault */
385 if (!strncasecmp(event_type, "gpu_fault", 9)) {
386 in.cur_time = (unsigned long)ktime / USEC_PER_SEC;
387 in.cur_cnt = pgpu->fail_cnt++;
388
389 ABC_PRINT("gpu fail count : %d\n", pgpu->fail_cnt);
390 sec_abc_enqueue(&pgpu->buffer, in);
391
392 /* Check gpu fault */
393 /* Case 1 : Over threshold count */
394 if (pgpu->fail_cnt >= pgpu->threshold_cnt) {
395 if (sec_abc_get_diff_time(&pgpu->buffer) < pgpu->threshold_time) {
396 ABC_PRINT("GPU fault occurred. Send uevent.\n");
397 kobject_uevent_env(&sec_abc->kobj, KOBJ_CHANGE, uevent_str);
398 }
399 pgpu->fail_cnt = 0;
400 sec_abc_dequeue(&pgpu->buffer, &out);
401 ABC_PRINT("cur_time : %lu cur_cnt : %d\n", out.cur_time, out.cur_cnt);
402 /* Case 2 : Check front and rear node in queue. Because it's occurred within max count */
403 } else if (sec_abc_is_full(&pgpu->buffer)) {
404 if (sec_abc_get_diff_time(&pgpu->buffer) < pgpu->threshold_time) {
405 ABC_PRINT("GPU fault occurred. Send uevent.\n");
406 kobject_uevent_env(&sec_abc->kobj, KOBJ_CHANGE, uevent_str);
407 }
408 sec_abc_dequeue(&pgpu->buffer, &out);
409 ABC_PRINT("cur_time : %lu cur_cnt : %d\n", out.cur_time, out.cur_cnt);
410 }
411
412 #ifdef ABC_WARNING_REPORT
413 /* Send GPU fault warning */
414 strcat(uevent_str[1], "_w");
415 kobject_uevent_env(&sec_abc->kobj, KOBJ_CHANGE, uevent_str);
416 #endif
417 } else if (!strncasecmp(event_type, "aicl", 4)) { /* AICL fault */
418 in.cur_time = (unsigned long)ktime / USEC_PER_SEC;
419 in.cur_cnt = paicl->fail_cnt++;
420
421 ABC_PRINT("aicl fail count : %d\n", paicl->fail_cnt);
422 sec_abc_enqueue(&paicl->buffer, in);
423
424 /* Check aicl fault */
425 if (paicl->fail_cnt >= paicl->threshold_cnt) {
426 if (sec_abc_get_diff_time(&paicl->buffer) < paicl->threshold_time) {
427 ABC_PRINT("AICL fault occurred. Send uevent.\n");
428 kobject_uevent_env(&sec_abc->kobj, KOBJ_CHANGE, uevent_str);
429 while (!sec_abc_is_empty(&paicl->buffer))
430 sec_abc_dequeue(&paicl->buffer, &out);
431 paicl->fail_cnt = 0;
432 } else {
433 paicl->fail_cnt--;
434 sec_abc_dequeue(&paicl->buffer, &out);
435 ABC_PRINT("cur_time : %lu cur_cnt : %d\n", out.cur_time, out.cur_cnt);
436 }
437 }
438 } else {
439 /* Others */
440 kobject_uevent_env(&sec_abc->kobj, KOBJ_CHANGE, uevent_str);
441 ABC_PRINT("Send uevent.\n");
442 }
443 } else { /* ABC_TYPE2_ENABLED */
444 kobject_uevent_env(&sec_abc->kobj, KOBJ_CHANGE, uevent_str);
445 ABC_PRINT("Send uevent.\n");
446 }
447 }
448
449 /* event string format
450 *
451 * ex) MODULE=tsp@ERROR=power_status_mismatch
452 * MODULE=tsp@ERROR=power_status_mismatch@EXT_LOG=fw_ver(0108)
453 *
454 */
455 void sec_abc_send_event(char *str)
456 {
457 struct abc_info *pinfo;
458
459 if (!abc_init) {
460 ABC_PRINT("ABC driver is not initialized!\n");
461 return;
462 }
463
464 if (abc_enabled == ABC_DISABLED) {
465 ABC_PRINT("ABC is disabled!\n");
466 return;
467 }
468
469 pinfo = dev_get_drvdata(sec_abc);
470
471 strlcpy(pinfo->abc_str, str, sizeof(pinfo->abc_str));
472 queue_work(pinfo->workqueue, &pinfo->work);
473 }
474 EXPORT_SYMBOL(sec_abc_send_event);
475
476 /**
477 * sec_abc_wait_enable() - wait for abc enable done
478 * Return : 0 for success, -1 for fail(timeout or abc not initialized)
479 */
480 int sec_abc_wait_enabled(void)
481 {
482 struct abc_info *pinfo;
483 unsigned long timeout;
484
485 if (!abc_init) {
486 ABC_PRINT("ABC driver is not initialized!\n");
487 return -1;
488 }
489
490 if (abc_enabled)
491 return 0;
492
493 pinfo = dev_get_drvdata(sec_abc);
494
495 reinit_completion(&pinfo->enable_done);
496
497 timeout = wait_for_completion_timeout(&pinfo->enable_done,
498 msecs_to_jiffies(ABC_WAIT_ENABLE_TIMEOUT));
499
500 if (timeout == 0) {
501 ABC_PRINT("%s : timeout!\n", __func__);
502 return -1;
503 }
504
505 return 0;
506 }
507 EXPORT_SYMBOL(sec_abc_wait_enabled);
508
509 static int sec_abc_probe(struct platform_device *pdev)
510 {
511 struct abc_platform_data *pdata;
512 struct abc_info *pinfo;
513 int ret = 0;
514
515 ABC_PRINT("%s\n", __func__);
516
517 abc_init = false;
518
519 if (pdev->dev.of_node) {
520 pdata = devm_kzalloc(&pdev->dev,
521 sizeof(struct abc_platform_data), GFP_KERNEL);
522
523 if (!pdata) {
524 dev_err(&pdev->dev, "Failed to allocate platform data\n");
525 return -ENOMEM;
526 }
527
528 pdev->dev.platform_data = pdata;
529 ret = abc_parse_dt(&pdev->dev);
530 if (ret) {
531 dev_err(&pdev->dev, "Failed to parse dt data\n");
532 return ret;
533 }
534
535 pr_info("%s: parse dt done\n", __func__);
536 } else {
537 pdata = pdev->dev.platform_data;
538 }
539
540 if (!pdata) {
541 dev_err(&pdev->dev, "There are no platform data\n");
542 return -EINVAL;
543 }
544
545 pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
546
547 if (!pinfo)
548 return -ENOMEM;
549
550 pinfo->dev = sec_device_create(pinfo, "sec_abc");
551 if (IS_ERR(pinfo->dev)) {
552 pr_err("%s Failed to create device(sec_abc)!\n", __func__);
553 ret = -ENODEV;
554 goto out;
555 }
556
557 ret = device_create_file(pinfo->dev, &dev_attr_enabled);
558 if (ret) {
559 pr_err("%s: Failed to create device enabled file\n", __func__);
560 goto err_create_abc_enabled_sysfs;
561 }
562
563 ret = device_create_file(pinfo->dev, &dev_attr_log);
564 if (ret) {
565 pr_err("%s: Failed to create device log file\n", __func__);
566 goto err_create_abc_log_sysfs;
567 }
568
569 INIT_WORK(&pinfo->work, sec_abc_work_func);
570
571 pinfo->workqueue = create_singlethread_workqueue("sec_abc_wq");
572 if (!pinfo->workqueue)
573 goto err_create_abc_wq;
574
575 INIT_LIST_HEAD(&pinfo->log_list);
576 pinfo->log_list_cnt = 0;
577
578 init_completion(&pinfo->enable_done);
579
580 sec_abc = pinfo->dev;
581 pinfo->pdata = pdata;
582
583 platform_set_drvdata(pdev, pinfo);
584
585 abc_init = true;
586 return ret;
587 err_create_abc_wq:
588 device_remove_file(pinfo->dev, &dev_attr_log);
589 err_create_abc_log_sysfs:
590 device_remove_file(pinfo->dev, &dev_attr_enabled);
591 err_create_abc_enabled_sysfs:
592 sec_device_destroy(sec_abc->devt);
593 out:
594 kfree(pinfo);
595 kfree(pdata);
596
597 return ret;
598 }
599
600 static struct platform_driver sec_abc_driver = {
601 .probe = sec_abc_probe,
602 .remove = sec_abc_remove,
603 .driver = {
604 .name = "sec_abc",
605 .owner = THIS_MODULE,
606 #if defined(CONFIG_PM)
607 .pm = &sec_abc_pm,
608 #endif
609 #if CONFIG_OF
610 .of_match_table = of_match_ptr(sec_abc_dt_match),
611 #endif
612 },
613 };
614
615 static int __init sec_abc_init(void)
616 {
617 ABC_PRINT("%s\n", __func__);
618
619 return platform_driver_register(&sec_abc_driver);
620 }
621
622 static void __exit sec_abc_exit(void)
623 {
624 return platform_driver_unregister(&sec_abc_driver);
625 }
626
627 module_init(sec_abc_init);
628 module_exit(sec_abc_exit);
629
630 MODULE_DESCRIPTION("Samsung ABC Driver");
631 MODULE_AUTHOR("Samsung Electronics");
632 MODULE_LICENSE("GPL");