MALI: rockchip: upgrade DDK to r8p0-02rel0.
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / midgard / mali_kbase_device.c
1 /*
2  *
3  * (C) COPYRIGHT 2010-2015 ARM Limited. All rights reserved.
4  *
5  * This program is free software and is provided to you under the terms of the
6  * GNU General Public License version 2 as published by the Free Software
7  * Foundation, and any use by you of this program is subject to the terms
8  * of such GNU licence.
9  *
10  * A copy of the licence is included with the program, and can also be obtained
11  * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
12  * Boston, MA  02110-1301, USA.
13  *
14  */
15
16
17
18
19
20 /*
21  * Base kernel device APIs
22  */
23
24 #include <linux/debugfs.h>
25 #include <linux/dma-mapping.h>
26 #include <linux/seq_file.h>
27 #include <linux/kernel.h>
28 #include <linux/module.h>
29 #include <linux/of_platform.h>
30
31 #include <mali_kbase.h>
32 #include <mali_kbase_defs.h>
33 #include <mali_kbase_hw.h>
34 #include <mali_kbase_config_defaults.h>
35
36 #include <mali_kbase_profiling_gator_api.h>
37
38 /* NOTE: Magic - 0x45435254 (TRCE in ASCII).
39  * Supports tracing feature provided in the base module.
40  * Please keep it in sync with the value of base module.
41  */
42 #define TRACE_BUFFER_HEADER_SPECIAL 0x45435254
43
44 #if KBASE_TRACE_ENABLE
45 static const char *kbasep_trace_code_string[] = {
46         /* IMPORTANT: USE OF SPECIAL #INCLUDE OF NON-STANDARD HEADER FILE
47          * THIS MUST BE USED AT THE START OF THE ARRAY */
48 #define KBASE_TRACE_CODE_MAKE_CODE(X) # X
49 #include "mali_kbase_trace_defs.h"
50 #undef  KBASE_TRACE_CODE_MAKE_CODE
51 };
52 #endif
53
54 #define DEBUG_MESSAGE_SIZE 256
55
56 static int kbasep_trace_init(struct kbase_device *kbdev);
57 static void kbasep_trace_term(struct kbase_device *kbdev);
58 static void kbasep_trace_hook_wrapper(void *param);
59
60 struct kbase_device *kbase_device_alloc(void)
61 {
62         return kzalloc(sizeof(struct kbase_device), GFP_KERNEL);
63 }
64
65 static int kbase_device_as_init(struct kbase_device *kbdev, int i)
66 {
67         const char format[] = "mali_mmu%d";
68         char name[sizeof(format)];
69         const char poke_format[] = "mali_mmu%d_poker";
70         char poke_name[sizeof(poke_format)];
71
72         if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316))
73                 snprintf(poke_name, sizeof(poke_name), poke_format, i);
74
75         snprintf(name, sizeof(name), format, i);
76
77         kbdev->as[i].number = i;
78         kbdev->as[i].fault_addr = 0ULL;
79
80         kbdev->as[i].pf_wq = alloc_workqueue(name, 0, 1);
81         if (!kbdev->as[i].pf_wq)
82                 return -EINVAL;
83
84         mutex_init(&kbdev->as[i].transaction_mutex);
85         INIT_WORK(&kbdev->as[i].work_pagefault, page_fault_worker);
86         INIT_WORK(&kbdev->as[i].work_busfault, bus_fault_worker);
87
88         if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316)) {
89                 struct hrtimer *poke_timer = &kbdev->as[i].poke_timer;
90                 struct work_struct *poke_work = &kbdev->as[i].poke_work;
91
92                 kbdev->as[i].poke_wq = alloc_workqueue(poke_name, 0, 1);
93                 if (!kbdev->as[i].poke_wq) {
94                         destroy_workqueue(kbdev->as[i].pf_wq);
95                         return -EINVAL;
96                 }
97                 KBASE_DEBUG_ASSERT(!object_is_on_stack(poke_work));
98                 INIT_WORK(poke_work, kbasep_as_do_poke);
99
100                 hrtimer_init(poke_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
101
102                 poke_timer->function = kbasep_as_poke_timer_callback;
103
104                 kbdev->as[i].poke_refcount = 0;
105                 kbdev->as[i].poke_state = 0u;
106         }
107
108         return 0;
109 }
110
111 static void kbase_device_as_term(struct kbase_device *kbdev, int i)
112 {
113         destroy_workqueue(kbdev->as[i].pf_wq);
114         if (kbase_hw_has_issue(kbdev, BASE_HW_ISSUE_8316))
115                 destroy_workqueue(kbdev->as[i].poke_wq);
116 }
117
118 static int kbase_device_all_as_init(struct kbase_device *kbdev)
119 {
120         int i, err;
121
122         for (i = 0; i < kbdev->nr_hw_address_spaces; i++) {
123                 err = kbase_device_as_init(kbdev, i);
124                 if (err)
125                         goto free_workqs;
126         }
127
128         return 0;
129
130 free_workqs:
131         for (; i > 0; i--)
132                 kbase_device_as_term(kbdev, i);
133
134         return err;
135 }
136
137 static void kbase_device_all_as_term(struct kbase_device *kbdev)
138 {
139         int i;
140
141         for (i = 0; i < kbdev->nr_hw_address_spaces; i++)
142                 kbase_device_as_term(kbdev, i);
143 }
144
145 int kbase_device_init(struct kbase_device * const kbdev)
146 {
147         int i, err;
148
149         spin_lock_init(&kbdev->mmu_mask_change);
150         /* Get the list of workarounds for issues on the current HW
151          * (identified by the GPU_ID register)
152          */
153         err = kbase_hw_set_issues_mask(kbdev);
154         if (err)
155                 goto fail;
156
157         /* Set the list of features available on the current HW
158          * (identified by the GPU_ID register)
159          */
160         kbase_hw_set_features_mask(kbdev);
161
162         kbase_gpuprops_set_features(kbdev);
163
164         /* On Linux 4.0+, dma coherency is determined from device tree */
165 #if defined(CONFIG_ARM64) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
166         set_dma_ops(kbdev->dev, &noncoherent_swiotlb_dma_ops);
167 #endif
168
169         /* Workaround a pre-3.13 Linux issue, where dma_mask is NULL when our
170          * device structure was created by device-tree
171          */
172         if (!kbdev->dev->dma_mask)
173                 kbdev->dev->dma_mask = &kbdev->dev->coherent_dma_mask;
174
175         err = dma_set_mask(kbdev->dev,
176                         DMA_BIT_MASK(kbdev->gpu_props.mmu.pa_bits));
177         if (err)
178                 goto dma_set_mask_failed;
179
180         err = dma_set_coherent_mask(kbdev->dev,
181                         DMA_BIT_MASK(kbdev->gpu_props.mmu.pa_bits));
182         if (err)
183                 goto dma_set_mask_failed;
184
185         kbdev->nr_hw_address_spaces = kbdev->gpu_props.num_address_spaces;
186
187         err = kbase_device_all_as_init(kbdev);
188         if (err)
189                 goto as_init_failed;
190
191         spin_lock_init(&kbdev->hwcnt.lock);
192
193         err = kbasep_trace_init(kbdev);
194         if (err)
195                 goto term_as;
196
197         mutex_init(&kbdev->cacheclean_lock);
198
199 #ifdef CONFIG_MALI_TRACE_TIMELINE
200         for (i = 0; i < BASE_JM_MAX_NR_SLOTS; ++i)
201                 kbdev->timeline.slot_atoms_submitted[i] = 0;
202
203         for (i = 0; i <= KBASEP_TIMELINE_PM_EVENT_LAST; ++i)
204                 atomic_set(&kbdev->timeline.pm_event_uid[i], 0);
205 #endif /* CONFIG_MALI_TRACE_TIMELINE */
206
207         /* fbdump profiling controls set to 0 - fbdump not enabled until changed by gator */
208         for (i = 0; i < FBDUMP_CONTROL_MAX; i++)
209                 kbdev->kbase_profiling_controls[i] = 0;
210
211         kbase_debug_assert_register_hook(&kbasep_trace_hook_wrapper, kbdev);
212
213         atomic_set(&kbdev->ctx_num, 0);
214
215         err = kbase_instr_backend_init(kbdev);
216         if (err)
217                 goto term_trace;
218
219         kbdev->pm.dvfs_period = DEFAULT_PM_DVFS_PERIOD;
220
221         kbdev->reset_timeout_ms = DEFAULT_RESET_TIMEOUT_MS;
222
223         kbdev->mmu_mode = kbase_mmu_mode_get_lpae();
224
225 #ifdef CONFIG_MALI_DEBUG
226         init_waitqueue_head(&kbdev->driver_inactive_wait);
227 #endif /* CONFIG_MALI_DEBUG */
228
229         return 0;
230 term_trace:
231         kbasep_trace_term(kbdev);
232 term_as:
233         kbase_device_all_as_term(kbdev);
234 as_init_failed:
235 dma_set_mask_failed:
236 fail:
237         return err;
238 }
239
240 void kbase_device_term(struct kbase_device *kbdev)
241 {
242         KBASE_DEBUG_ASSERT(kbdev);
243
244 #if KBASE_TRACE_ENABLE
245         kbase_debug_assert_register_hook(NULL, NULL);
246 #endif
247
248         kbase_instr_backend_term(kbdev);
249
250         kbasep_trace_term(kbdev);
251
252         kbase_device_all_as_term(kbdev);
253 }
254
255 void kbase_device_free(struct kbase_device *kbdev)
256 {
257         kfree(kbdev);
258 }
259
260 void kbase_device_trace_buffer_install(struct kbase_context *kctx, u32 *tb, size_t size)
261 {
262         unsigned long flags;
263
264         KBASE_DEBUG_ASSERT(kctx);
265         KBASE_DEBUG_ASSERT(tb);
266
267         /* set up the header */
268         /* magic number in the first 4 bytes */
269         tb[0] = TRACE_BUFFER_HEADER_SPECIAL;
270         /* Store (write offset = 0, wrap counter = 0, transaction active = no)
271          * write offset 0 means never written.
272          * Offsets 1 to (wrap_offset - 1) used to store values when trace started
273          */
274         tb[1] = 0;
275
276         /* install trace buffer */
277         spin_lock_irqsave(&kctx->jctx.tb_lock, flags);
278         kctx->jctx.tb_wrap_offset = size / 8;
279         kctx->jctx.tb = tb;
280         spin_unlock_irqrestore(&kctx->jctx.tb_lock, flags);
281 }
282
283 void kbase_device_trace_buffer_uninstall(struct kbase_context *kctx)
284 {
285         unsigned long flags;
286
287         KBASE_DEBUG_ASSERT(kctx);
288         spin_lock_irqsave(&kctx->jctx.tb_lock, flags);
289         kctx->jctx.tb = NULL;
290         kctx->jctx.tb_wrap_offset = 0;
291         spin_unlock_irqrestore(&kctx->jctx.tb_lock, flags);
292 }
293
294 void kbase_device_trace_register_access(struct kbase_context *kctx, enum kbase_reg_access_type type, u16 reg_offset, u32 reg_value)
295 {
296         unsigned long flags;
297
298         spin_lock_irqsave(&kctx->jctx.tb_lock, flags);
299         if (kctx->jctx.tb) {
300                 u16 wrap_count;
301                 u16 write_offset;
302                 u32 *tb = kctx->jctx.tb;
303                 u32 header_word;
304
305                 header_word = tb[1];
306                 KBASE_DEBUG_ASSERT(0 == (header_word & 0x1));
307
308                 wrap_count = (header_word >> 1) & 0x7FFF;
309                 write_offset = (header_word >> 16) & 0xFFFF;
310
311                 /* mark as transaction in progress */
312                 tb[1] |= 0x1;
313                 mb();
314
315                 /* calculate new offset */
316                 write_offset++;
317                 if (write_offset == kctx->jctx.tb_wrap_offset) {
318                         /* wrap */
319                         write_offset = 1;
320                         wrap_count++;
321                         wrap_count &= 0x7FFF;   /* 15bit wrap counter */
322                 }
323
324                 /* store the trace entry at the selected offset */
325                 tb[write_offset * 2 + 0] = (reg_offset & ~0x3) | ((type == REG_WRITE) ? 0x1 : 0x0);
326                 tb[write_offset * 2 + 1] = reg_value;
327                 mb();
328
329                 /* new header word */
330                 header_word = (write_offset << 16) | (wrap_count << 1) | 0x0;   /* transaction complete */
331                 tb[1] = header_word;
332         }
333         spin_unlock_irqrestore(&kctx->jctx.tb_lock, flags);
334 }
335
336 /*
337  * Device trace functions
338  */
339 #if KBASE_TRACE_ENABLE
340
341 static int kbasep_trace_init(struct kbase_device *kbdev)
342 {
343         struct kbase_trace *rbuf;
344
345         rbuf = kmalloc_array(KBASE_TRACE_SIZE, sizeof(*rbuf), GFP_KERNEL);
346
347         if (!rbuf)
348                 return -EINVAL;
349
350         kbdev->trace_rbuf = rbuf;
351         spin_lock_init(&kbdev->trace_lock);
352         return 0;
353 }
354
355 static void kbasep_trace_term(struct kbase_device *kbdev)
356 {
357         kfree(kbdev->trace_rbuf);
358 }
359
360 static void kbasep_trace_format_msg(struct kbase_trace *trace_msg, char *buffer, int len)
361 {
362         s32 written = 0;
363
364         /* Initial part of message */
365         written += MAX(snprintf(buffer + written, MAX(len - written, 0), "%d.%.6d,%d,%d,%s,%p,", (int)trace_msg->timestamp.tv_sec, (int)(trace_msg->timestamp.tv_nsec / 1000), trace_msg->thread_id, trace_msg->cpu, kbasep_trace_code_string[trace_msg->code], trace_msg->ctx), 0);
366
367         if (trace_msg->katom)
368                 written += MAX(snprintf(buffer + written, MAX(len - written, 0), "atom %d (ud: 0x%llx 0x%llx)", trace_msg->atom_number, trace_msg->atom_udata[0], trace_msg->atom_udata[1]), 0);
369
370         written += MAX(snprintf(buffer + written, MAX(len - written, 0), ",%.8llx,", trace_msg->gpu_addr), 0);
371
372         /* NOTE: Could add function callbacks to handle different message types */
373         /* Jobslot present */
374         if (trace_msg->flags & KBASE_TRACE_FLAG_JOBSLOT)
375                 written += MAX(snprintf(buffer + written, MAX(len - written, 0), "%d", trace_msg->jobslot), 0);
376
377         written += MAX(snprintf(buffer + written, MAX(len - written, 0), ","), 0);
378
379         /* Refcount present */
380         if (trace_msg->flags & KBASE_TRACE_FLAG_REFCOUNT)
381                 written += MAX(snprintf(buffer + written, MAX(len - written, 0), "%d", trace_msg->refcount), 0);
382
383         written += MAX(snprintf(buffer + written, MAX(len - written, 0), ","), 0);
384
385         /* Rest of message */
386         written += MAX(snprintf(buffer + written, MAX(len - written, 0), "0x%.8lx", trace_msg->info_val), 0);
387 }
388
389 static void kbasep_trace_dump_msg(struct kbase_device *kbdev, struct kbase_trace *trace_msg)
390 {
391         char buffer[DEBUG_MESSAGE_SIZE];
392
393         kbasep_trace_format_msg(trace_msg, buffer, DEBUG_MESSAGE_SIZE);
394         dev_dbg(kbdev->dev, "%s", buffer);
395 }
396
397 void kbasep_trace_add(struct kbase_device *kbdev, enum kbase_trace_code code, void *ctx, struct kbase_jd_atom *katom, u64 gpu_addr, u8 flags, int refcount, int jobslot, unsigned long info_val)
398 {
399         unsigned long irqflags;
400         struct kbase_trace *trace_msg;
401
402         spin_lock_irqsave(&kbdev->trace_lock, irqflags);
403
404         trace_msg = &kbdev->trace_rbuf[kbdev->trace_next_in];
405
406         /* Fill the message */
407         trace_msg->thread_id = task_pid_nr(current);
408         trace_msg->cpu = task_cpu(current);
409
410         getnstimeofday(&trace_msg->timestamp);
411
412         trace_msg->code = code;
413         trace_msg->ctx = ctx;
414
415         if (NULL == katom) {
416                 trace_msg->katom = false;
417         } else {
418                 trace_msg->katom = true;
419                 trace_msg->atom_number = kbase_jd_atom_id(katom->kctx, katom);
420                 trace_msg->atom_udata[0] = katom->udata.blob[0];
421                 trace_msg->atom_udata[1] = katom->udata.blob[1];
422         }
423
424         trace_msg->gpu_addr = gpu_addr;
425         trace_msg->jobslot = jobslot;
426         trace_msg->refcount = MIN((unsigned int)refcount, 0xFF);
427         trace_msg->info_val = info_val;
428         trace_msg->flags = flags;
429
430         /* Update the ringbuffer indices */
431         kbdev->trace_next_in = (kbdev->trace_next_in + 1) & KBASE_TRACE_MASK;
432         if (kbdev->trace_next_in == kbdev->trace_first_out)
433                 kbdev->trace_first_out = (kbdev->trace_first_out + 1) & KBASE_TRACE_MASK;
434
435         /* Done */
436
437         spin_unlock_irqrestore(&kbdev->trace_lock, irqflags);
438 }
439
440 void kbasep_trace_clear(struct kbase_device *kbdev)
441 {
442         unsigned long flags;
443
444         spin_lock_irqsave(&kbdev->trace_lock, flags);
445         kbdev->trace_first_out = kbdev->trace_next_in;
446         spin_unlock_irqrestore(&kbdev->trace_lock, flags);
447 }
448
449 void kbasep_trace_dump(struct kbase_device *kbdev)
450 {
451         unsigned long flags;
452         u32 start;
453         u32 end;
454
455         dev_dbg(kbdev->dev, "Dumping trace:\nsecs,nthread,cpu,code,ctx,katom,gpu_addr,jobslot,refcount,info_val");
456         spin_lock_irqsave(&kbdev->trace_lock, flags);
457         start = kbdev->trace_first_out;
458         end = kbdev->trace_next_in;
459
460         while (start != end) {
461                 struct kbase_trace *trace_msg = &kbdev->trace_rbuf[start];
462
463                 kbasep_trace_dump_msg(kbdev, trace_msg);
464
465                 start = (start + 1) & KBASE_TRACE_MASK;
466         }
467         dev_dbg(kbdev->dev, "TRACE_END");
468
469         spin_unlock_irqrestore(&kbdev->trace_lock, flags);
470
471         KBASE_TRACE_CLEAR(kbdev);
472 }
473
474 static void kbasep_trace_hook_wrapper(void *param)
475 {
476         struct kbase_device *kbdev = (struct kbase_device *)param;
477
478         kbasep_trace_dump(kbdev);
479 }
480
481 #ifdef CONFIG_DEBUG_FS
482 struct trace_seq_state {
483         struct kbase_trace trace_buf[KBASE_TRACE_SIZE];
484         u32 start;
485         u32 end;
486 };
487
488 static void *kbasep_trace_seq_start(struct seq_file *s, loff_t *pos)
489 {
490         struct trace_seq_state *state = s->private;
491         int i;
492
493         if (*pos > KBASE_TRACE_SIZE)
494                 return NULL;
495         i = state->start + *pos;
496         if ((state->end >= state->start && i >= state->end) ||
497                         i >= state->end + KBASE_TRACE_SIZE)
498                 return NULL;
499
500         i &= KBASE_TRACE_MASK;
501
502         return &state->trace_buf[i];
503 }
504
505 static void kbasep_trace_seq_stop(struct seq_file *s, void *data)
506 {
507 }
508
509 static void *kbasep_trace_seq_next(struct seq_file *s, void *data, loff_t *pos)
510 {
511         struct trace_seq_state *state = s->private;
512         int i;
513
514         (*pos)++;
515
516         i = (state->start + *pos) & KBASE_TRACE_MASK;
517         if (i == state->end)
518                 return NULL;
519
520         return &state->trace_buf[i];
521 }
522
523 static int kbasep_trace_seq_show(struct seq_file *s, void *data)
524 {
525         struct kbase_trace *trace_msg = data;
526         char buffer[DEBUG_MESSAGE_SIZE];
527
528         kbasep_trace_format_msg(trace_msg, buffer, DEBUG_MESSAGE_SIZE);
529         seq_printf(s, "%s\n", buffer);
530         return 0;
531 }
532
533 static const struct seq_operations kbasep_trace_seq_ops = {
534         .start = kbasep_trace_seq_start,
535         .next = kbasep_trace_seq_next,
536         .stop = kbasep_trace_seq_stop,
537         .show = kbasep_trace_seq_show,
538 };
539
540 static int kbasep_trace_debugfs_open(struct inode *inode, struct file *file)
541 {
542         struct kbase_device *kbdev = inode->i_private;
543         unsigned long flags;
544
545         struct trace_seq_state *state;
546
547         state = __seq_open_private(file, &kbasep_trace_seq_ops, sizeof(*state));
548         if (!state)
549                 return -ENOMEM;
550
551         spin_lock_irqsave(&kbdev->trace_lock, flags);
552         state->start = kbdev->trace_first_out;
553         state->end = kbdev->trace_next_in;
554         memcpy(state->trace_buf, kbdev->trace_rbuf, sizeof(state->trace_buf));
555         spin_unlock_irqrestore(&kbdev->trace_lock, flags);
556
557         return 0;
558 }
559
560 static const struct file_operations kbasep_trace_debugfs_fops = {
561         .open = kbasep_trace_debugfs_open,
562         .read = seq_read,
563         .llseek = seq_lseek,
564         .release = seq_release_private,
565 };
566
567 void kbasep_trace_debugfs_init(struct kbase_device *kbdev)
568 {
569         debugfs_create_file("mali_trace", S_IRUGO,
570                         kbdev->mali_debugfs_directory, kbdev,
571                         &kbasep_trace_debugfs_fops);
572 }
573
574 #else
575 void kbasep_trace_debugfs_init(struct kbase_device *kbdev)
576 {
577 }
578 #endif                          /* CONFIG_DEBUG_FS */
579
580 #else                           /* KBASE_TRACE_ENABLE  */
581 static int kbasep_trace_init(struct kbase_device *kbdev)
582 {
583         CSTD_UNUSED(kbdev);
584         return 0;
585 }
586
587 static void kbasep_trace_term(struct kbase_device *kbdev)
588 {
589         CSTD_UNUSED(kbdev);
590 }
591
592 static void kbasep_trace_hook_wrapper(void *param)
593 {
594         CSTD_UNUSED(param);
595 }
596
597 void kbasep_trace_dump(struct kbase_device *kbdev)
598 {
599         CSTD_UNUSED(kbdev);
600 }
601 #endif                          /* KBASE_TRACE_ENABLE  */
602
603 void kbase_set_profiling_control(struct kbase_device *kbdev, u32 control, u32 value)
604 {
605         switch (control) {
606         case FBDUMP_CONTROL_ENABLE:
607                 /* fall through */
608         case FBDUMP_CONTROL_RATE:
609                 /* fall through */
610         case SW_COUNTER_ENABLE:
611                 /* fall through */
612         case FBDUMP_CONTROL_RESIZE_FACTOR:
613                 kbdev->kbase_profiling_controls[control] = value;
614                 break;
615         default:
616                 dev_err(kbdev->dev, "Profiling control %d not found\n", control);
617                 break;
618         }
619 }
620
621 u32 kbase_get_profiling_control(struct kbase_device *kbdev, u32 control)
622 {
623         u32 ret_value = 0;
624
625         switch (control) {
626         case FBDUMP_CONTROL_ENABLE:
627                 /* fall through */
628         case FBDUMP_CONTROL_RATE:
629                 /* fall through */
630         case SW_COUNTER_ENABLE:
631                 /* fall through */
632         case FBDUMP_CONTROL_RESIZE_FACTOR:
633                 ret_value = kbdev->kbase_profiling_controls[control];
634                 break;
635         default:
636                 dev_err(kbdev->dev, "Profiling control %d not found\n", control);
637                 break;
638         }
639
640         return ret_value;
641 }
642
643 /*
644  * Called by gator to control the production of
645  * profiling information at runtime
646  * */
647
648 void _mali_profiling_control(u32 action, u32 value)
649 {
650         struct kbase_device *kbdev = NULL;
651
652         /* find the first i.e. call with -1 */
653         kbdev = kbase_find_device(-1);
654
655         if (NULL != kbdev)
656                 kbase_set_profiling_control(kbdev, action, value);
657 }
658 KBASE_EXPORT_SYMBOL(_mali_profiling_control);
659