1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
// SPDX-License-Identifier: GPL-2.0-only OR MIT
/* Copyright (c) 2023 Imagination Technologies Ltd. */
#include "pvr_device.h"
#include "pvr_gem.h"
#include "pvr_rogue_fwif.h"
#include "pvr_fw_trace.h"
#include <drm/drm_file.h>
#include <linux/build_bug.h>
#include <linux/dcache.h>
#include <linux/sysfs.h>
#include <linux/types.h>
static void
tracebuf_ctrl_init(void *cpu_ptr, void *priv)
{
struct rogue_fwif_tracebuf *tracebuf_ctrl = cpu_ptr;
struct pvr_fw_trace *fw_trace = priv;
u32 thread_nr;
tracebuf_ctrl->tracebuf_size_in_dwords = ROGUE_FW_TRACE_BUF_DEFAULT_SIZE_IN_DWORDS;
tracebuf_ctrl->tracebuf_flags = 0;
if (fw_trace->group_mask)
tracebuf_ctrl->log_type = fw_trace->group_mask | ROGUE_FWIF_LOG_TYPE_TRACE;
else
tracebuf_ctrl->log_type = ROGUE_FWIF_LOG_TYPE_NONE;
for (thread_nr = 0; thread_nr < ARRAY_SIZE(fw_trace->buffers); thread_nr++) {
struct rogue_fwif_tracebuf_space *tracebuf_space =
&tracebuf_ctrl->tracebuf[thread_nr];
struct pvr_fw_trace_buffer *trace_buffer = &fw_trace->buffers[thread_nr];
pvr_fw_object_get_fw_addr(trace_buffer->buf_obj,
&tracebuf_space->trace_buffer_fw_addr);
tracebuf_space->trace_buffer = trace_buffer->buf;
tracebuf_space->trace_pointer = 0;
}
}
int pvr_fw_trace_init(struct pvr_device *pvr_dev)
{
struct pvr_fw_trace *fw_trace = &pvr_dev->fw_dev.fw_trace;
struct drm_device *drm_dev = from_pvr_device(pvr_dev);
u32 thread_nr;
int err;
for (thread_nr = 0; thread_nr < ARRAY_SIZE(fw_trace->buffers); thread_nr++) {
struct pvr_fw_trace_buffer *trace_buffer = &fw_trace->buffers[thread_nr];
trace_buffer->buf =
pvr_fw_object_create_and_map(pvr_dev,
ROGUE_FW_TRACE_BUF_DEFAULT_SIZE_IN_DWORDS *
sizeof(*trace_buffer->buf),
PVR_BO_FW_FLAGS_DEVICE_UNCACHED |
PVR_BO_FW_NO_CLEAR_ON_RESET,
NULL, NULL, &trace_buffer->buf_obj);
if (IS_ERR(trace_buffer->buf)) {
drm_err(drm_dev, "Unable to allocate trace buffer\n");
err = PTR_ERR(trace_buffer->buf);
trace_buffer->buf = NULL;
goto err_free_buf;
}
}
/* TODO: Provide control of group mask. */
fw_trace->group_mask = 0;
fw_trace->tracebuf_ctrl =
pvr_fw_object_create_and_map(pvr_dev,
sizeof(*fw_trace->tracebuf_ctrl),
PVR_BO_FW_FLAGS_DEVICE_UNCACHED |
PVR_BO_FW_NO_CLEAR_ON_RESET,
tracebuf_ctrl_init, fw_trace,
&fw_trace->tracebuf_ctrl_obj);
if (IS_ERR(fw_trace->tracebuf_ctrl)) {
drm_err(drm_dev, "Unable to allocate trace buffer control structure\n");
err = PTR_ERR(fw_trace->tracebuf_ctrl);
goto err_free_buf;
}
BUILD_BUG_ON(ARRAY_SIZE(fw_trace->tracebuf_ctrl->tracebuf) !=
ARRAY_SIZE(fw_trace->buffers));
for (thread_nr = 0; thread_nr < ARRAY_SIZE(fw_trace->buffers); thread_nr++) {
struct rogue_fwif_tracebuf_space *tracebuf_space =
&fw_trace->tracebuf_ctrl->tracebuf[thread_nr];
struct pvr_fw_trace_buffer *trace_buffer = &fw_trace->buffers[thread_nr];
trace_buffer->tracebuf_space = tracebuf_space;
}
return 0;
err_free_buf:
for (thread_nr = 0; thread_nr < ARRAY_SIZE(fw_trace->buffers); thread_nr++) {
struct pvr_fw_trace_buffer *trace_buffer = &fw_trace->buffers[thread_nr];
if (trace_buffer->buf)
pvr_fw_object_unmap_and_destroy(trace_buffer->buf_obj);
}
return err;
}
void pvr_fw_trace_fini(struct pvr_device *pvr_dev)
{
struct pvr_fw_trace *fw_trace = &pvr_dev->fw_dev.fw_trace;
u32 thread_nr;
for (thread_nr = 0; thread_nr < ARRAY_SIZE(fw_trace->buffers); thread_nr++) {
struct pvr_fw_trace_buffer *trace_buffer = &fw_trace->buffers[thread_nr];
pvr_fw_object_unmap_and_destroy(trace_buffer->buf_obj);
}
pvr_fw_object_unmap_and_destroy(fw_trace->tracebuf_ctrl_obj);
}
|