.. | .. |
---|
1 | 1 | // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note |
---|
2 | 2 | /* |
---|
3 | 3 | * |
---|
4 | | - * (C) COPYRIGHT 2018-2021 ARM Limited. All rights reserved. |
---|
| 4 | + * (C) COPYRIGHT 2018-2022 ARM Limited. All rights reserved. |
---|
5 | 5 | * |
---|
6 | 6 | * This program is free software and is provided to you under the terms of the |
---|
7 | 7 | * GNU General Public License version 2 as published by the Free Software |
---|
.. | .. |
---|
29 | 29 | #include <linux/list.h> |
---|
30 | 30 | #include <linux/mman.h> |
---|
31 | 31 | |
---|
32 | | -#if IS_ENABLED(CONFIG_DEBUG_FS) |
---|
33 | | -#if (KERNEL_VERSION(4, 7, 0) > LINUX_VERSION_CODE) |
---|
34 | | -#define DEFINE_DEBUGFS_ATTRIBUTE DEFINE_SIMPLE_ATTRIBUTE |
---|
35 | | -#endif |
---|
36 | | -#endif |
---|
37 | | - |
---|
38 | 32 | /** |
---|
39 | 33 | * struct firmware_trace_buffer - Trace Buffer within the MCU firmware |
---|
40 | | - * |
---|
41 | | - * The firmware relays information to the host by writing on memory buffers |
---|
42 | | - * which are allocated and partially configured by the host. These buffers |
---|
43 | | - * are called Trace Buffers: each of them has a specific purpose and is |
---|
44 | | - * identified by a name and a set of memory addresses where the host can |
---|
45 | | - * set pointers to host-allocated structures. |
---|
46 | 34 | * |
---|
47 | 35 | * @kbdev: Pointer to the Kbase device. |
---|
48 | 36 | * @node: List head linking all trace buffers to |
---|
.. | .. |
---|
73 | 61 | * @num_pages: Size of the data buffer, in pages. |
---|
74 | 62 | * @trace_enable_init_mask: Initial value for the trace enable bit mask. |
---|
75 | 63 | * @name: NULL terminated string which contains the name of the trace buffer. |
---|
| 64 | + * |
---|
| 65 | + * The firmware relays information to the host by writing on memory buffers |
---|
| 66 | + * which are allocated and partially configured by the host. These buffers |
---|
| 67 | + * are called Trace Buffers: each of them has a specific purpose and is |
---|
| 68 | + * identified by a name and a set of memory addresses where the host can |
---|
| 69 | + * set pointers to host-allocated structures. |
---|
76 | 70 | */ |
---|
77 | 71 | struct firmware_trace_buffer { |
---|
78 | 72 | struct kbase_device *kbdev; |
---|
.. | .. |
---|
100 | 94 | /** |
---|
101 | 95 | * struct firmware_trace_buffer_data - Configuration data for trace buffers |
---|
102 | 96 | * |
---|
103 | | - * Describe how to set up a trace buffer interface. |
---|
104 | | - * Trace buffers are identified by name and they require a data buffer and |
---|
105 | | - * an initial mask of values for the trace enable bits. |
---|
106 | | - * |
---|
107 | 97 | * @name: Name identifier of the trace buffer |
---|
108 | 98 | * @trace_enable_init_mask: Initial value to assign to the trace enable bits |
---|
109 | 99 | * @size: Size of the data buffer to allocate for the trace buffer, in pages. |
---|
110 | 100 | * The size of a data buffer must always be a power of 2. |
---|
| 101 | + * |
---|
| 102 | + * Describe how to set up a trace buffer interface. |
---|
| 103 | + * Trace buffers are identified by name and they require a data buffer and |
---|
| 104 | + * an initial mask of values for the trace enable bits. |
---|
111 | 105 | */ |
---|
112 | 106 | struct firmware_trace_buffer_data { |
---|
113 | 107 | char name[64]; |
---|
.. | .. |
---|
121 | 115 | * This table contains the configuration data for the trace buffers that are |
---|
122 | 116 | * expected to be parsed from the firmware. |
---|
123 | 117 | */ |
---|
124 | | -static const struct firmware_trace_buffer_data |
---|
125 | | -trace_buffer_data[] = { |
---|
126 | | -#ifndef MALI_KBASE_BUILD |
---|
127 | | - { "fwutf", {0}, 1 }, |
---|
| 118 | +static const struct firmware_trace_buffer_data trace_buffer_data[] = { |
---|
| 119 | +#if MALI_UNIT_TEST |
---|
| 120 | + { "fwutf", { 0 }, 1 }, |
---|
128 | 121 | #endif |
---|
129 | | - { FW_TRACE_BUF_NAME, {0}, 4 }, |
---|
130 | | - { "benchmark", {0}, 2 }, |
---|
131 | | - { "timeline", {0}, KBASE_CSF_TL_BUFFER_NR_PAGES }, |
---|
| 122 | + { FIRMWARE_LOG_BUF_NAME, { 0 }, 4 }, |
---|
| 123 | + { "benchmark", { 0 }, 2 }, |
---|
| 124 | + { "timeline", { 0 }, KBASE_CSF_TL_BUFFER_NR_PAGES }, |
---|
132 | 125 | }; |
---|
133 | 126 | |
---|
134 | 127 | int kbase_csf_firmware_trace_buffers_init(struct kbase_device *kbdev) |
---|
.. | .. |
---|
180 | 173 | extract_gpu_va = |
---|
181 | 174 | (kbdev->csf.firmware_trace_buffers.mcu_rw.va_reg->start_pfn << PAGE_SHIFT) + |
---|
182 | 175 | mcu_rw_offset; |
---|
183 | | - extract_cpu_va = (u32*)( |
---|
| 176 | + extract_cpu_va = (u32 *)( |
---|
184 | 177 | kbdev->csf.firmware_trace_buffers.mcu_rw.cpu_addr + |
---|
185 | 178 | mcu_rw_offset); |
---|
186 | 179 | insert_gpu_va = |
---|
187 | 180 | (kbdev->csf.firmware_trace_buffers.mcu_write.va_reg->start_pfn << PAGE_SHIFT) + |
---|
188 | 181 | mcu_write_offset; |
---|
189 | | - insert_cpu_va = (u32*)( |
---|
| 182 | + insert_cpu_va = (u32 *)( |
---|
190 | 183 | kbdev->csf.firmware_trace_buffers.mcu_write.cpu_addr + |
---|
191 | 184 | mcu_write_offset); |
---|
192 | 185 | data_buffer_gpu_va = |
---|
.. | .. |
---|
324 | 317 | extract_gpu_va = |
---|
325 | 318 | (kbdev->csf.firmware_trace_buffers.mcu_rw.va_reg->start_pfn << PAGE_SHIFT) + |
---|
326 | 319 | mcu_rw_offset; |
---|
327 | | - extract_cpu_va = (u32*)( |
---|
| 320 | + extract_cpu_va = (u32 *)( |
---|
328 | 321 | kbdev->csf.firmware_trace_buffers.mcu_rw.cpu_addr + |
---|
329 | 322 | mcu_rw_offset); |
---|
330 | 323 | insert_gpu_va = |
---|
331 | 324 | (kbdev->csf.firmware_trace_buffers.mcu_write.va_reg->start_pfn << PAGE_SHIFT) + |
---|
332 | 325 | mcu_write_offset; |
---|
333 | | - insert_cpu_va = (u32*)( |
---|
| 326 | + insert_cpu_va = (u32 *)( |
---|
334 | 327 | kbdev->csf.firmware_trace_buffers.mcu_write.cpu_addr + |
---|
335 | 328 | mcu_write_offset); |
---|
336 | 329 | data_buffer_gpu_va = |
---|
.. | .. |
---|
513 | 506 | } |
---|
514 | 507 | EXPORT_SYMBOL(kbase_csf_firmware_trace_buffer_read_data); |
---|
515 | 508 | |
---|
516 | | -#if IS_ENABLED(CONFIG_DEBUG_FS) |
---|
| 509 | +static void update_trace_buffer_active_mask64(struct firmware_trace_buffer *tb, u64 mask) |
---|
| 510 | +{ |
---|
| 511 | + unsigned int i; |
---|
| 512 | + |
---|
| 513 | + for (i = 0; i < tb->trace_enable_entry_count; i++) |
---|
| 514 | + kbasep_csf_firmware_trace_buffer_update_trace_enable_bit(tb, i, (mask >> i) & 1); |
---|
| 515 | +} |
---|
517 | 516 | |
---|
518 | 517 | #define U32_BITS 32 |
---|
519 | | -static u64 get_trace_buffer_active_mask64(struct firmware_trace_buffer *tb) |
---|
| 518 | +u64 kbase_csf_firmware_trace_buffer_get_active_mask64(struct firmware_trace_buffer *tb) |
---|
520 | 519 | { |
---|
521 | 520 | u64 active_mask = tb->trace_enable_init_mask[0]; |
---|
522 | 521 | |
---|
.. | .. |
---|
526 | 525 | return active_mask; |
---|
527 | 526 | } |
---|
528 | 527 | |
---|
529 | | -static void update_trace_buffer_active_mask64(struct firmware_trace_buffer *tb, |
---|
530 | | - u64 mask) |
---|
531 | | -{ |
---|
532 | | - unsigned int i; |
---|
533 | | - |
---|
534 | | - for (i = 0; i < tb->trace_enable_entry_count; i++) |
---|
535 | | - kbasep_csf_firmware_trace_buffer_update_trace_enable_bit( |
---|
536 | | - tb, i, (mask >> i) & 1); |
---|
537 | | -} |
---|
538 | | - |
---|
539 | | -static int set_trace_buffer_active_mask64(struct firmware_trace_buffer *tb, |
---|
540 | | - u64 mask) |
---|
| 528 | +int kbase_csf_firmware_trace_buffer_set_active_mask64(struct firmware_trace_buffer *tb, u64 mask) |
---|
541 | 529 | { |
---|
542 | 530 | struct kbase_device *kbdev = tb->kbdev; |
---|
543 | 531 | unsigned long flags; |
---|
.. | .. |
---|
565 | 553 | |
---|
566 | 554 | return err; |
---|
567 | 555 | } |
---|
568 | | - |
---|
569 | | -static int kbase_csf_firmware_trace_enable_mask_read(void *data, u64 *val) |
---|
570 | | -{ |
---|
571 | | - struct kbase_device *kbdev = (struct kbase_device *)data; |
---|
572 | | - struct firmware_trace_buffer *tb = |
---|
573 | | - kbase_csf_firmware_get_trace_buffer(kbdev, FW_TRACE_BUF_NAME); |
---|
574 | | - |
---|
575 | | - if (tb == NULL) { |
---|
576 | | - dev_err(kbdev->dev, "Couldn't get the firmware trace buffer"); |
---|
577 | | - return -EIO; |
---|
578 | | - } |
---|
579 | | - /* The enabled traces limited to u64 here, regarded practical */ |
---|
580 | | - *val = get_trace_buffer_active_mask64(tb); |
---|
581 | | - return 0; |
---|
582 | | -} |
---|
583 | | - |
---|
584 | | -static int kbase_csf_firmware_trace_enable_mask_write(void *data, u64 val) |
---|
585 | | -{ |
---|
586 | | - struct kbase_device *kbdev = (struct kbase_device *)data; |
---|
587 | | - struct firmware_trace_buffer *tb = |
---|
588 | | - kbase_csf_firmware_get_trace_buffer(kbdev, FW_TRACE_BUF_NAME); |
---|
589 | | - u64 new_mask; |
---|
590 | | - unsigned int enable_bits_count; |
---|
591 | | - |
---|
592 | | - if (tb == NULL) { |
---|
593 | | - dev_err(kbdev->dev, "Couldn't get the firmware trace buffer"); |
---|
594 | | - return -EIO; |
---|
595 | | - } |
---|
596 | | - |
---|
597 | | - /* Ignore unsupported types */ |
---|
598 | | - enable_bits_count = |
---|
599 | | - kbase_csf_firmware_trace_buffer_get_trace_enable_bits_count(tb); |
---|
600 | | - if (enable_bits_count > 64) { |
---|
601 | | - dev_dbg(kbdev->dev, "Limit enabled bits count from %u to 64", |
---|
602 | | - enable_bits_count); |
---|
603 | | - enable_bits_count = 64; |
---|
604 | | - } |
---|
605 | | - new_mask = val & ((1 << enable_bits_count) - 1); |
---|
606 | | - |
---|
607 | | - if (new_mask != get_trace_buffer_active_mask64(tb)) |
---|
608 | | - return set_trace_buffer_active_mask64(tb, new_mask); |
---|
609 | | - else |
---|
610 | | - return 0; |
---|
611 | | -} |
---|
612 | | - |
---|
613 | | -static int kbasep_csf_firmware_trace_debugfs_open(struct inode *in, |
---|
614 | | - struct file *file) |
---|
615 | | -{ |
---|
616 | | - struct kbase_device *kbdev = in->i_private; |
---|
617 | | - |
---|
618 | | - file->private_data = kbdev; |
---|
619 | | - dev_dbg(kbdev->dev, "Opened firmware trace buffer dump debugfs file"); |
---|
620 | | - |
---|
621 | | - return 0; |
---|
622 | | -} |
---|
623 | | - |
---|
624 | | -static ssize_t kbasep_csf_firmware_trace_debugfs_read(struct file *file, |
---|
625 | | - char __user *buf, size_t size, loff_t *ppos) |
---|
626 | | -{ |
---|
627 | | - struct kbase_device *kbdev = file->private_data; |
---|
628 | | - u8 *pbyte; |
---|
629 | | - unsigned int n_read; |
---|
630 | | - unsigned long not_copied; |
---|
631 | | - /* Limit the kernel buffer to no more than two pages */ |
---|
632 | | - size_t mem = MIN(size, 2 * PAGE_SIZE); |
---|
633 | | - unsigned long flags; |
---|
634 | | - |
---|
635 | | - struct firmware_trace_buffer *tb = |
---|
636 | | - kbase_csf_firmware_get_trace_buffer(kbdev, FW_TRACE_BUF_NAME); |
---|
637 | | - |
---|
638 | | - if (tb == NULL) { |
---|
639 | | - dev_err(kbdev->dev, "Couldn't get the firmware trace buffer"); |
---|
640 | | - return -EIO; |
---|
641 | | - } |
---|
642 | | - |
---|
643 | | - pbyte = kmalloc(mem, GFP_KERNEL); |
---|
644 | | - if (pbyte == NULL) { |
---|
645 | | - dev_err(kbdev->dev, "Couldn't allocate memory for trace buffer dump"); |
---|
646 | | - return -ENOMEM; |
---|
647 | | - } |
---|
648 | | - |
---|
649 | | - spin_lock_irqsave(&kbdev->hwaccess_lock, flags); |
---|
650 | | - n_read = kbase_csf_firmware_trace_buffer_read_data(tb, pbyte, mem); |
---|
651 | | - spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); |
---|
652 | | - |
---|
653 | | - /* Do the copy, if we have obtained some trace data */ |
---|
654 | | - not_copied = (n_read) ? copy_to_user(buf, pbyte, n_read) : 0; |
---|
655 | | - kfree(pbyte); |
---|
656 | | - |
---|
657 | | - if (!not_copied) { |
---|
658 | | - *ppos += n_read; |
---|
659 | | - return n_read; |
---|
660 | | - } |
---|
661 | | - |
---|
662 | | - dev_err(kbdev->dev, "Couldn't copy trace buffer data to user space buffer"); |
---|
663 | | - return -EFAULT; |
---|
664 | | -} |
---|
665 | | - |
---|
666 | | - |
---|
667 | | -DEFINE_SIMPLE_ATTRIBUTE(kbase_csf_firmware_trace_enable_mask_fops, |
---|
668 | | - kbase_csf_firmware_trace_enable_mask_read, |
---|
669 | | - kbase_csf_firmware_trace_enable_mask_write, "%llx\n"); |
---|
670 | | - |
---|
671 | | -static const struct file_operations kbasep_csf_firmware_trace_debugfs_fops = { |
---|
672 | | - .owner = THIS_MODULE, |
---|
673 | | - .open = kbasep_csf_firmware_trace_debugfs_open, |
---|
674 | | - .read = kbasep_csf_firmware_trace_debugfs_read, |
---|
675 | | - .llseek = no_llseek, |
---|
676 | | -}; |
---|
677 | | - |
---|
678 | | -void kbase_csf_firmware_trace_buffer_debugfs_init(struct kbase_device *kbdev) |
---|
679 | | -{ |
---|
680 | | - debugfs_create_file("fw_trace_enable_mask", 0644, |
---|
681 | | - kbdev->mali_debugfs_directory, kbdev, |
---|
682 | | - &kbase_csf_firmware_trace_enable_mask_fops); |
---|
683 | | - |
---|
684 | | - debugfs_create_file("fw_traces", 0444, |
---|
685 | | - kbdev->mali_debugfs_directory, kbdev, |
---|
686 | | - &kbasep_csf_firmware_trace_debugfs_fops); |
---|
687 | | -} |
---|
688 | | -#endif /* CONFIG_DEBUG_FS */ |
---|