1*e65e175bSOded Gabbay // SPDX-License-Identifier: GPL-2.0
2*e65e175bSOded Gabbay
3*e65e175bSOded Gabbay /*
4*e65e175bSOded Gabbay * Copyright 2021 HabanaLabs, Ltd.
5*e65e175bSOded Gabbay * All Rights Reserved.
6*e65e175bSOded Gabbay */
7*e65e175bSOded Gabbay
8*e65e175bSOded Gabbay #include <linux/vmalloc.h>
9*e65e175bSOded Gabbay #include <uapi/drm/habanalabs_accel.h>
10*e65e175bSOded Gabbay #include "habanalabs.h"
11*e65e175bSOded Gabbay
12*e65e175bSOded Gabbay /**
13*e65e175bSOded Gabbay * hl_format_as_binary - helper function, format an integer as binary
14*e65e175bSOded Gabbay * using supplied scratch buffer
15*e65e175bSOded Gabbay * @buf: the buffer to use
16*e65e175bSOded Gabbay * @buf_len: buffer capacity
17*e65e175bSOded Gabbay * @n: number to format
18*e65e175bSOded Gabbay *
19*e65e175bSOded Gabbay * Returns pointer to buffer
20*e65e175bSOded Gabbay */
hl_format_as_binary(char * buf,size_t buf_len,u32 n)21*e65e175bSOded Gabbay char *hl_format_as_binary(char *buf, size_t buf_len, u32 n)
22*e65e175bSOded Gabbay {
23*e65e175bSOded Gabbay int i;
24*e65e175bSOded Gabbay u32 bit;
25*e65e175bSOded Gabbay bool leading0 = true;
26*e65e175bSOded Gabbay char *wrptr = buf;
27*e65e175bSOded Gabbay
28*e65e175bSOded Gabbay if (buf_len > 0 && buf_len < 3) {
29*e65e175bSOded Gabbay *wrptr = '\0';
30*e65e175bSOded Gabbay return buf;
31*e65e175bSOded Gabbay }
32*e65e175bSOded Gabbay
33*e65e175bSOded Gabbay wrptr[0] = '0';
34*e65e175bSOded Gabbay wrptr[1] = 'b';
35*e65e175bSOded Gabbay wrptr += 2;
36*e65e175bSOded Gabbay /* Remove 3 characters from length for '0b' and '\0' termination */
37*e65e175bSOded Gabbay buf_len -= 3;
38*e65e175bSOded Gabbay
39*e65e175bSOded Gabbay for (i = 0; i < sizeof(n) * BITS_PER_BYTE && buf_len; ++i, n <<= 1) {
40*e65e175bSOded Gabbay /* Writing bit calculation in one line would cause a false
41*e65e175bSOded Gabbay * positive static code analysis error, so splitting.
42*e65e175bSOded Gabbay */
43*e65e175bSOded Gabbay bit = n & (1 << (sizeof(n) * BITS_PER_BYTE - 1));
44*e65e175bSOded Gabbay bit = !!bit;
45*e65e175bSOded Gabbay leading0 &= !bit;
46*e65e175bSOded Gabbay if (!leading0) {
47*e65e175bSOded Gabbay *wrptr = '0' + bit;
48*e65e175bSOded Gabbay ++wrptr;
49*e65e175bSOded Gabbay }
50*e65e175bSOded Gabbay }
51*e65e175bSOded Gabbay
52*e65e175bSOded Gabbay *wrptr = '\0';
53*e65e175bSOded Gabbay
54*e65e175bSOded Gabbay return buf;
55*e65e175bSOded Gabbay }
56*e65e175bSOded Gabbay
57*e65e175bSOded Gabbay /**
58*e65e175bSOded Gabbay * resize_to_fit - helper function, resize buffer to fit given amount of data
59*e65e175bSOded Gabbay * @buf: destination buffer double pointer
60*e65e175bSOded Gabbay * @size: pointer to the size container
61*e65e175bSOded Gabbay * @desired_size: size the buffer must contain
62*e65e175bSOded Gabbay *
63*e65e175bSOded Gabbay * Returns 0 on success or error code on failure.
64*e65e175bSOded Gabbay * On success, the size of buffer is at least desired_size. Buffer is allocated
65*e65e175bSOded Gabbay * via vmalloc and must be freed with vfree.
66*e65e175bSOded Gabbay */
resize_to_fit(char ** buf,size_t * size,size_t desired_size)67*e65e175bSOded Gabbay static int resize_to_fit(char **buf, size_t *size, size_t desired_size)
68*e65e175bSOded Gabbay {
69*e65e175bSOded Gabbay char *resized_buf;
70*e65e175bSOded Gabbay size_t new_size;
71*e65e175bSOded Gabbay
72*e65e175bSOded Gabbay if (*size >= desired_size)
73*e65e175bSOded Gabbay return 0;
74*e65e175bSOded Gabbay
75*e65e175bSOded Gabbay /* Not enough space to print all, have to resize */
76*e65e175bSOded Gabbay new_size = max_t(size_t, PAGE_SIZE, round_up(desired_size, PAGE_SIZE));
77*e65e175bSOded Gabbay resized_buf = vmalloc(new_size);
78*e65e175bSOded Gabbay if (!resized_buf)
79*e65e175bSOded Gabbay return -ENOMEM;
80*e65e175bSOded Gabbay memcpy(resized_buf, *buf, *size);
81*e65e175bSOded Gabbay vfree(*buf);
82*e65e175bSOded Gabbay *buf = resized_buf;
83*e65e175bSOded Gabbay *size = new_size;
84*e65e175bSOded Gabbay
85*e65e175bSOded Gabbay return 1;
86*e65e175bSOded Gabbay }
87*e65e175bSOded Gabbay
88*e65e175bSOded Gabbay /**
89*e65e175bSOded Gabbay * hl_snprintf_resize() - print formatted data to buffer, resize as needed
90*e65e175bSOded Gabbay * @buf: buffer double pointer, to be written to and resized, must be either
91*e65e175bSOded Gabbay * NULL or allocated with vmalloc.
92*e65e175bSOded Gabbay * @size: current size of the buffer
93*e65e175bSOded Gabbay * @offset: current offset to write to
94*e65e175bSOded Gabbay * @format: format of the data
95*e65e175bSOded Gabbay *
96*e65e175bSOded Gabbay * This function will write formatted data into the buffer. If buffer is not
97*e65e175bSOded Gabbay * large enough, it will be resized using vmalloc. Size may be modified if the
98*e65e175bSOded Gabbay * buffer was resized, offset will be advanced by the number of bytes written
99*e65e175bSOded Gabbay * not including the terminating character
100*e65e175bSOded Gabbay *
101*e65e175bSOded Gabbay * Returns 0 on success or error code on failure
102*e65e175bSOded Gabbay *
103*e65e175bSOded Gabbay * Note that the buffer has to be manually released using vfree.
104*e65e175bSOded Gabbay */
hl_snprintf_resize(char ** buf,size_t * size,size_t * offset,const char * format,...)105*e65e175bSOded Gabbay int hl_snprintf_resize(char **buf, size_t *size, size_t *offset,
106*e65e175bSOded Gabbay const char *format, ...)
107*e65e175bSOded Gabbay {
108*e65e175bSOded Gabbay va_list args;
109*e65e175bSOded Gabbay size_t length;
110*e65e175bSOded Gabbay int rc;
111*e65e175bSOded Gabbay
112*e65e175bSOded Gabbay if (*buf == NULL && (*size != 0 || *offset != 0))
113*e65e175bSOded Gabbay return -EINVAL;
114*e65e175bSOded Gabbay
115*e65e175bSOded Gabbay va_start(args, format);
116*e65e175bSOded Gabbay length = vsnprintf(*buf + *offset, *size - *offset, format, args);
117*e65e175bSOded Gabbay va_end(args);
118*e65e175bSOded Gabbay
119*e65e175bSOded Gabbay rc = resize_to_fit(buf, size, *offset + length + 1);
120*e65e175bSOded Gabbay if (rc < 0)
121*e65e175bSOded Gabbay return rc;
122*e65e175bSOded Gabbay else if (rc > 0) {
123*e65e175bSOded Gabbay /* Resize was needed, write again */
124*e65e175bSOded Gabbay va_start(args, format);
125*e65e175bSOded Gabbay length = vsnprintf(*buf + *offset, *size - *offset, format,
126*e65e175bSOded Gabbay args);
127*e65e175bSOded Gabbay va_end(args);
128*e65e175bSOded Gabbay }
129*e65e175bSOded Gabbay
130*e65e175bSOded Gabbay *offset += length;
131*e65e175bSOded Gabbay
132*e65e175bSOded Gabbay return 0;
133*e65e175bSOded Gabbay }
134*e65e175bSOded Gabbay
135*e65e175bSOded Gabbay /**
136*e65e175bSOded Gabbay * hl_sync_engine_to_string - convert engine type enum to string literal
137*e65e175bSOded Gabbay * @engine_type: engine type (TPC/MME/DMA)
138*e65e175bSOded Gabbay *
139*e65e175bSOded Gabbay * Return the resolved string literal
140*e65e175bSOded Gabbay */
hl_sync_engine_to_string(enum hl_sync_engine_type engine_type)141*e65e175bSOded Gabbay const char *hl_sync_engine_to_string(enum hl_sync_engine_type engine_type)
142*e65e175bSOded Gabbay {
143*e65e175bSOded Gabbay switch (engine_type) {
144*e65e175bSOded Gabbay case ENGINE_DMA:
145*e65e175bSOded Gabbay return "DMA";
146*e65e175bSOded Gabbay case ENGINE_MME:
147*e65e175bSOded Gabbay return "MME";
148*e65e175bSOded Gabbay case ENGINE_TPC:
149*e65e175bSOded Gabbay return "TPC";
150*e65e175bSOded Gabbay }
151*e65e175bSOded Gabbay return "Invalid Engine Type";
152*e65e175bSOded Gabbay }
153*e65e175bSOded Gabbay
154*e65e175bSOded Gabbay /**
155*e65e175bSOded Gabbay * hl_print_resize_sync_engine - helper function, format engine name and ID
156*e65e175bSOded Gabbay * using hl_snprintf_resize
157*e65e175bSOded Gabbay * @buf: destination buffer double pointer to be used with hl_snprintf_resize
158*e65e175bSOded Gabbay * @size: pointer to the size container
159*e65e175bSOded Gabbay * @offset: pointer to the offset container
160*e65e175bSOded Gabbay * @engine_type: engine type (TPC/MME/DMA)
161*e65e175bSOded Gabbay * @engine_id: engine numerical id
162*e65e175bSOded Gabbay *
163*e65e175bSOded Gabbay * Returns 0 on success or error code on failure
164*e65e175bSOded Gabbay */
hl_print_resize_sync_engine(char ** buf,size_t * size,size_t * offset,enum hl_sync_engine_type engine_type,u32 engine_id)165*e65e175bSOded Gabbay static int hl_print_resize_sync_engine(char **buf, size_t *size, size_t *offset,
166*e65e175bSOded Gabbay enum hl_sync_engine_type engine_type,
167*e65e175bSOded Gabbay u32 engine_id)
168*e65e175bSOded Gabbay {
169*e65e175bSOded Gabbay return hl_snprintf_resize(buf, size, offset, "%s%u",
170*e65e175bSOded Gabbay hl_sync_engine_to_string(engine_type), engine_id);
171*e65e175bSOded Gabbay }
172*e65e175bSOded Gabbay
173*e65e175bSOded Gabbay /**
174*e65e175bSOded Gabbay * hl_state_dump_get_sync_name - transform sync object id to name if available
175*e65e175bSOded Gabbay * @hdev: pointer to the device
176*e65e175bSOded Gabbay * @sync_id: sync object id
177*e65e175bSOded Gabbay *
178*e65e175bSOded Gabbay * Returns a name literal or NULL if not resolved.
179*e65e175bSOded Gabbay * Note: returning NULL shall not be considered as a failure, as not all
180*e65e175bSOded Gabbay * sync objects are named.
181*e65e175bSOded Gabbay */
hl_state_dump_get_sync_name(struct hl_device * hdev,u32 sync_id)182*e65e175bSOded Gabbay const char *hl_state_dump_get_sync_name(struct hl_device *hdev, u32 sync_id)
183*e65e175bSOded Gabbay {
184*e65e175bSOded Gabbay struct hl_state_dump_specs *sds = &hdev->state_dump_specs;
185*e65e175bSOded Gabbay struct hl_hw_obj_name_entry *entry;
186*e65e175bSOded Gabbay
187*e65e175bSOded Gabbay hash_for_each_possible(sds->so_id_to_str_tb, entry,
188*e65e175bSOded Gabbay node, sync_id)
189*e65e175bSOded Gabbay if (sync_id == entry->id)
190*e65e175bSOded Gabbay return entry->name;
191*e65e175bSOded Gabbay
192*e65e175bSOded Gabbay return NULL;
193*e65e175bSOded Gabbay }
194*e65e175bSOded Gabbay
195*e65e175bSOded Gabbay /**
196*e65e175bSOded Gabbay * hl_state_dump_get_monitor_name - transform monitor object dump to monitor
197*e65e175bSOded Gabbay * name if available
198*e65e175bSOded Gabbay * @hdev: pointer to the device
199*e65e175bSOded Gabbay * @mon: monitor state dump
200*e65e175bSOded Gabbay *
201*e65e175bSOded Gabbay * Returns a name literal or NULL if not resolved.
202*e65e175bSOded Gabbay * Note: returning NULL shall not be considered as a failure, as not all
203*e65e175bSOded Gabbay * monitors are named.
204*e65e175bSOded Gabbay */
hl_state_dump_get_monitor_name(struct hl_device * hdev,struct hl_mon_state_dump * mon)205*e65e175bSOded Gabbay const char *hl_state_dump_get_monitor_name(struct hl_device *hdev,
206*e65e175bSOded Gabbay struct hl_mon_state_dump *mon)
207*e65e175bSOded Gabbay {
208*e65e175bSOded Gabbay struct hl_state_dump_specs *sds = &hdev->state_dump_specs;
209*e65e175bSOded Gabbay struct hl_hw_obj_name_entry *entry;
210*e65e175bSOded Gabbay
211*e65e175bSOded Gabbay hash_for_each_possible(sds->monitor_id_to_str_tb,
212*e65e175bSOded Gabbay entry, node, mon->id)
213*e65e175bSOded Gabbay if (mon->id == entry->id)
214*e65e175bSOded Gabbay return entry->name;
215*e65e175bSOded Gabbay
216*e65e175bSOded Gabbay return NULL;
217*e65e175bSOded Gabbay }
218*e65e175bSOded Gabbay
219*e65e175bSOded Gabbay /**
220*e65e175bSOded Gabbay * hl_state_dump_free_sync_to_engine_map - free sync object to engine map
221*e65e175bSOded Gabbay * @map: sync object to engine map
222*e65e175bSOded Gabbay *
223*e65e175bSOded Gabbay * Note: generic free implementation, the allocation is implemented per ASIC.
224*e65e175bSOded Gabbay */
hl_state_dump_free_sync_to_engine_map(struct hl_sync_to_engine_map * map)225*e65e175bSOded Gabbay void hl_state_dump_free_sync_to_engine_map(struct hl_sync_to_engine_map *map)
226*e65e175bSOded Gabbay {
227*e65e175bSOded Gabbay struct hl_sync_to_engine_map_entry *entry;
228*e65e175bSOded Gabbay struct hlist_node *tmp_node;
229*e65e175bSOded Gabbay int i;
230*e65e175bSOded Gabbay
231*e65e175bSOded Gabbay hash_for_each_safe(map->tb, i, tmp_node, entry, node) {
232*e65e175bSOded Gabbay hash_del(&entry->node);
233*e65e175bSOded Gabbay kfree(entry);
234*e65e175bSOded Gabbay }
235*e65e175bSOded Gabbay }
236*e65e175bSOded Gabbay
237*e65e175bSOded Gabbay /**
238*e65e175bSOded Gabbay * hl_state_dump_get_sync_to_engine - transform sync_id to
239*e65e175bSOded Gabbay * hl_sync_to_engine_map_entry if available for current id
240*e65e175bSOded Gabbay * @map: sync object to engine map
241*e65e175bSOded Gabbay * @sync_id: sync object id
242*e65e175bSOded Gabbay *
243*e65e175bSOded Gabbay * Returns the translation entry if found or NULL if not.
244*e65e175bSOded Gabbay * Note, returned NULL shall not be considered as a failure as the map
245*e65e175bSOded Gabbay * does not cover all possible, it is a best effort sync ids.
246*e65e175bSOded Gabbay */
247*e65e175bSOded Gabbay static struct hl_sync_to_engine_map_entry *
hl_state_dump_get_sync_to_engine(struct hl_sync_to_engine_map * map,u32 sync_id)248*e65e175bSOded Gabbay hl_state_dump_get_sync_to_engine(struct hl_sync_to_engine_map *map, u32 sync_id)
249*e65e175bSOded Gabbay {
250*e65e175bSOded Gabbay struct hl_sync_to_engine_map_entry *entry;
251*e65e175bSOded Gabbay
252*e65e175bSOded Gabbay hash_for_each_possible(map->tb, entry, node, sync_id)
253*e65e175bSOded Gabbay if (entry->sync_id == sync_id)
254*e65e175bSOded Gabbay return entry;
255*e65e175bSOded Gabbay return NULL;
256*e65e175bSOded Gabbay }
257*e65e175bSOded Gabbay
258*e65e175bSOded Gabbay /**
259*e65e175bSOded Gabbay * hl_state_dump_read_sync_objects - read sync objects array
260*e65e175bSOded Gabbay * @hdev: pointer to the device
261*e65e175bSOded Gabbay * @index: sync manager block index starting with E_N
262*e65e175bSOded Gabbay *
263*e65e175bSOded Gabbay * Returns array of size SP_SYNC_OBJ_AMOUNT on success or NULL on failure
264*e65e175bSOded Gabbay */
hl_state_dump_read_sync_objects(struct hl_device * hdev,u32 index)265*e65e175bSOded Gabbay static u32 *hl_state_dump_read_sync_objects(struct hl_device *hdev, u32 index)
266*e65e175bSOded Gabbay {
267*e65e175bSOded Gabbay struct hl_state_dump_specs *sds = &hdev->state_dump_specs;
268*e65e175bSOded Gabbay u32 *sync_objects;
269*e65e175bSOded Gabbay s64 base_addr; /* Base addr can be negative */
270*e65e175bSOded Gabbay int i;
271*e65e175bSOded Gabbay
272*e65e175bSOded Gabbay base_addr = sds->props[SP_SYNC_OBJ_BASE_ADDR] +
273*e65e175bSOded Gabbay sds->props[SP_NEXT_SYNC_OBJ_ADDR] * index;
274*e65e175bSOded Gabbay
275*e65e175bSOded Gabbay sync_objects = vmalloc(sds->props[SP_SYNC_OBJ_AMOUNT] * sizeof(u32));
276*e65e175bSOded Gabbay if (!sync_objects)
277*e65e175bSOded Gabbay return NULL;
278*e65e175bSOded Gabbay
279*e65e175bSOded Gabbay for (i = 0; i < sds->props[SP_SYNC_OBJ_AMOUNT]; ++i)
280*e65e175bSOded Gabbay sync_objects[i] = RREG32(base_addr + i * sizeof(u32));
281*e65e175bSOded Gabbay
282*e65e175bSOded Gabbay return sync_objects;
283*e65e175bSOded Gabbay }
284*e65e175bSOded Gabbay
285*e65e175bSOded Gabbay /**
286*e65e175bSOded Gabbay * hl_state_dump_free_sync_objects - free sync objects array allocated by
287*e65e175bSOded Gabbay * hl_state_dump_read_sync_objects
288*e65e175bSOded Gabbay * @sync_objects: sync objects array
289*e65e175bSOded Gabbay */
hl_state_dump_free_sync_objects(u32 * sync_objects)290*e65e175bSOded Gabbay static void hl_state_dump_free_sync_objects(u32 *sync_objects)
291*e65e175bSOded Gabbay {
292*e65e175bSOded Gabbay vfree(sync_objects);
293*e65e175bSOded Gabbay }
294*e65e175bSOded Gabbay
295*e65e175bSOded Gabbay
296*e65e175bSOded Gabbay /**
297*e65e175bSOded Gabbay * hl_state_dump_print_syncs_single_block - print active sync objects on a
298*e65e175bSOded Gabbay * single block
299*e65e175bSOded Gabbay * @hdev: pointer to the device
300*e65e175bSOded Gabbay * @index: sync manager block index starting with E_N
301*e65e175bSOded Gabbay * @buf: destination buffer double pointer to be used with hl_snprintf_resize
302*e65e175bSOded Gabbay * @size: pointer to the size container
303*e65e175bSOded Gabbay * @offset: pointer to the offset container
304*e65e175bSOded Gabbay * @map: sync engines names map
305*e65e175bSOded Gabbay *
306*e65e175bSOded Gabbay * Returns 0 on success or error code on failure
307*e65e175bSOded Gabbay */
308*e65e175bSOded Gabbay static int
hl_state_dump_print_syncs_single_block(struct hl_device * hdev,u32 index,char ** buf,size_t * size,size_t * offset,struct hl_sync_to_engine_map * map)309*e65e175bSOded Gabbay hl_state_dump_print_syncs_single_block(struct hl_device *hdev, u32 index,
310*e65e175bSOded Gabbay char **buf, size_t *size, size_t *offset,
311*e65e175bSOded Gabbay struct hl_sync_to_engine_map *map)
312*e65e175bSOded Gabbay {
313*e65e175bSOded Gabbay struct hl_state_dump_specs *sds = &hdev->state_dump_specs;
314*e65e175bSOded Gabbay const char *sync_name;
315*e65e175bSOded Gabbay u32 *sync_objects = NULL;
316*e65e175bSOded Gabbay int rc = 0, i;
317*e65e175bSOded Gabbay
318*e65e175bSOded Gabbay if (sds->sync_namager_names) {
319*e65e175bSOded Gabbay rc = hl_snprintf_resize(
320*e65e175bSOded Gabbay buf, size, offset, "%s\n",
321*e65e175bSOded Gabbay sds->sync_namager_names[index]);
322*e65e175bSOded Gabbay if (rc)
323*e65e175bSOded Gabbay goto out;
324*e65e175bSOded Gabbay }
325*e65e175bSOded Gabbay
326*e65e175bSOded Gabbay sync_objects = hl_state_dump_read_sync_objects(hdev, index);
327*e65e175bSOded Gabbay if (!sync_objects) {
328*e65e175bSOded Gabbay rc = -ENOMEM;
329*e65e175bSOded Gabbay goto out;
330*e65e175bSOded Gabbay }
331*e65e175bSOded Gabbay
332*e65e175bSOded Gabbay for (i = 0; i < sds->props[SP_SYNC_OBJ_AMOUNT]; ++i) {
333*e65e175bSOded Gabbay struct hl_sync_to_engine_map_entry *entry;
334*e65e175bSOded Gabbay u64 sync_object_addr;
335*e65e175bSOded Gabbay
336*e65e175bSOded Gabbay if (!sync_objects[i])
337*e65e175bSOded Gabbay continue;
338*e65e175bSOded Gabbay
339*e65e175bSOded Gabbay sync_object_addr = sds->props[SP_SYNC_OBJ_BASE_ADDR] +
340*e65e175bSOded Gabbay sds->props[SP_NEXT_SYNC_OBJ_ADDR] * index +
341*e65e175bSOded Gabbay i * sizeof(u32);
342*e65e175bSOded Gabbay
343*e65e175bSOded Gabbay rc = hl_snprintf_resize(buf, size, offset, "sync id: %u", i);
344*e65e175bSOded Gabbay if (rc)
345*e65e175bSOded Gabbay goto free_sync_objects;
346*e65e175bSOded Gabbay sync_name = hl_state_dump_get_sync_name(hdev, i);
347*e65e175bSOded Gabbay if (sync_name) {
348*e65e175bSOded Gabbay rc = hl_snprintf_resize(buf, size, offset, " %s",
349*e65e175bSOded Gabbay sync_name);
350*e65e175bSOded Gabbay if (rc)
351*e65e175bSOded Gabbay goto free_sync_objects;
352*e65e175bSOded Gabbay }
353*e65e175bSOded Gabbay rc = hl_snprintf_resize(buf, size, offset, ", value: %u",
354*e65e175bSOded Gabbay sync_objects[i]);
355*e65e175bSOded Gabbay if (rc)
356*e65e175bSOded Gabbay goto free_sync_objects;
357*e65e175bSOded Gabbay
358*e65e175bSOded Gabbay /* Append engine string */
359*e65e175bSOded Gabbay entry = hl_state_dump_get_sync_to_engine(map,
360*e65e175bSOded Gabbay (u32)sync_object_addr);
361*e65e175bSOded Gabbay if (entry) {
362*e65e175bSOded Gabbay rc = hl_snprintf_resize(buf, size, offset,
363*e65e175bSOded Gabbay ", Engine: ");
364*e65e175bSOded Gabbay if (rc)
365*e65e175bSOded Gabbay goto free_sync_objects;
366*e65e175bSOded Gabbay rc = hl_print_resize_sync_engine(buf, size, offset,
367*e65e175bSOded Gabbay entry->engine_type,
368*e65e175bSOded Gabbay entry->engine_id);
369*e65e175bSOded Gabbay if (rc)
370*e65e175bSOded Gabbay goto free_sync_objects;
371*e65e175bSOded Gabbay }
372*e65e175bSOded Gabbay
373*e65e175bSOded Gabbay rc = hl_snprintf_resize(buf, size, offset, "\n");
374*e65e175bSOded Gabbay if (rc)
375*e65e175bSOded Gabbay goto free_sync_objects;
376*e65e175bSOded Gabbay }
377*e65e175bSOded Gabbay
378*e65e175bSOded Gabbay free_sync_objects:
379*e65e175bSOded Gabbay hl_state_dump_free_sync_objects(sync_objects);
380*e65e175bSOded Gabbay out:
381*e65e175bSOded Gabbay return rc;
382*e65e175bSOded Gabbay }
383*e65e175bSOded Gabbay
384*e65e175bSOded Gabbay /**
385*e65e175bSOded Gabbay * hl_state_dump_print_syncs - print active sync objects
386*e65e175bSOded Gabbay * @hdev: pointer to the device
387*e65e175bSOded Gabbay * @buf: destination buffer double pointer to be used with hl_snprintf_resize
388*e65e175bSOded Gabbay * @size: pointer to the size container
389*e65e175bSOded Gabbay * @offset: pointer to the offset container
390*e65e175bSOded Gabbay *
391*e65e175bSOded Gabbay * Returns 0 on success or error code on failure
392*e65e175bSOded Gabbay */
hl_state_dump_print_syncs(struct hl_device * hdev,char ** buf,size_t * size,size_t * offset)393*e65e175bSOded Gabbay static int hl_state_dump_print_syncs(struct hl_device *hdev,
394*e65e175bSOded Gabbay char **buf, size_t *size,
395*e65e175bSOded Gabbay size_t *offset)
396*e65e175bSOded Gabbay
397*e65e175bSOded Gabbay {
398*e65e175bSOded Gabbay struct hl_state_dump_specs *sds = &hdev->state_dump_specs;
399*e65e175bSOded Gabbay struct hl_sync_to_engine_map *map;
400*e65e175bSOded Gabbay u32 index;
401*e65e175bSOded Gabbay int rc = 0;
402*e65e175bSOded Gabbay
403*e65e175bSOded Gabbay map = kzalloc(sizeof(*map), GFP_KERNEL);
404*e65e175bSOded Gabbay if (!map)
405*e65e175bSOded Gabbay return -ENOMEM;
406*e65e175bSOded Gabbay
407*e65e175bSOded Gabbay rc = sds->funcs.gen_sync_to_engine_map(hdev, map);
408*e65e175bSOded Gabbay if (rc)
409*e65e175bSOded Gabbay goto free_map_mem;
410*e65e175bSOded Gabbay
411*e65e175bSOded Gabbay rc = hl_snprintf_resize(buf, size, offset, "Non zero sync objects:\n");
412*e65e175bSOded Gabbay if (rc)
413*e65e175bSOded Gabbay goto out;
414*e65e175bSOded Gabbay
415*e65e175bSOded Gabbay if (sds->sync_namager_names) {
416*e65e175bSOded Gabbay for (index = 0; sds->sync_namager_names[index]; ++index) {
417*e65e175bSOded Gabbay rc = hl_state_dump_print_syncs_single_block(
418*e65e175bSOded Gabbay hdev, index, buf, size, offset, map);
419*e65e175bSOded Gabbay if (rc)
420*e65e175bSOded Gabbay goto out;
421*e65e175bSOded Gabbay }
422*e65e175bSOded Gabbay } else {
423*e65e175bSOded Gabbay for (index = 0; index < sds->props[SP_NUM_CORES]; ++index) {
424*e65e175bSOded Gabbay rc = hl_state_dump_print_syncs_single_block(
425*e65e175bSOded Gabbay hdev, index, buf, size, offset, map);
426*e65e175bSOded Gabbay if (rc)
427*e65e175bSOded Gabbay goto out;
428*e65e175bSOded Gabbay }
429*e65e175bSOded Gabbay }
430*e65e175bSOded Gabbay
431*e65e175bSOded Gabbay out:
432*e65e175bSOded Gabbay hl_state_dump_free_sync_to_engine_map(map);
433*e65e175bSOded Gabbay free_map_mem:
434*e65e175bSOded Gabbay kfree(map);
435*e65e175bSOded Gabbay
436*e65e175bSOded Gabbay return rc;
437*e65e175bSOded Gabbay }
438*e65e175bSOded Gabbay
439*e65e175bSOded Gabbay /**
440*e65e175bSOded Gabbay * hl_state_dump_alloc_read_sm_block_monitors - read monitors for a specific
441*e65e175bSOded Gabbay * block
442*e65e175bSOded Gabbay * @hdev: pointer to the device
443*e65e175bSOded Gabbay * @index: sync manager block index starting with E_N
444*e65e175bSOded Gabbay *
445*e65e175bSOded Gabbay * Returns an array of monitor data of size SP_MONITORS_AMOUNT or NULL
446*e65e175bSOded Gabbay * on error
447*e65e175bSOded Gabbay */
448*e65e175bSOded Gabbay static struct hl_mon_state_dump *
hl_state_dump_alloc_read_sm_block_monitors(struct hl_device * hdev,u32 index)449*e65e175bSOded Gabbay hl_state_dump_alloc_read_sm_block_monitors(struct hl_device *hdev, u32 index)
450*e65e175bSOded Gabbay {
451*e65e175bSOded Gabbay struct hl_state_dump_specs *sds = &hdev->state_dump_specs;
452*e65e175bSOded Gabbay struct hl_mon_state_dump *monitors;
453*e65e175bSOded Gabbay s64 base_addr; /* Base addr can be negative */
454*e65e175bSOded Gabbay int i;
455*e65e175bSOded Gabbay
456*e65e175bSOded Gabbay monitors = vmalloc(sds->props[SP_MONITORS_AMOUNT] *
457*e65e175bSOded Gabbay sizeof(struct hl_mon_state_dump));
458*e65e175bSOded Gabbay if (!monitors)
459*e65e175bSOded Gabbay return NULL;
460*e65e175bSOded Gabbay
461*e65e175bSOded Gabbay base_addr = sds->props[SP_NEXT_SYNC_OBJ_ADDR] * index;
462*e65e175bSOded Gabbay
463*e65e175bSOded Gabbay for (i = 0; i < sds->props[SP_MONITORS_AMOUNT]; ++i) {
464*e65e175bSOded Gabbay monitors[i].id = i;
465*e65e175bSOded Gabbay monitors[i].wr_addr_low =
466*e65e175bSOded Gabbay RREG32(base_addr + sds->props[SP_MON_OBJ_WR_ADDR_LOW] +
467*e65e175bSOded Gabbay i * sizeof(u32));
468*e65e175bSOded Gabbay
469*e65e175bSOded Gabbay monitors[i].wr_addr_high =
470*e65e175bSOded Gabbay RREG32(base_addr + sds->props[SP_MON_OBJ_WR_ADDR_HIGH] +
471*e65e175bSOded Gabbay i * sizeof(u32));
472*e65e175bSOded Gabbay
473*e65e175bSOded Gabbay monitors[i].wr_data =
474*e65e175bSOded Gabbay RREG32(base_addr + sds->props[SP_MON_OBJ_WR_DATA] +
475*e65e175bSOded Gabbay i * sizeof(u32));
476*e65e175bSOded Gabbay
477*e65e175bSOded Gabbay monitors[i].arm_data =
478*e65e175bSOded Gabbay RREG32(base_addr + sds->props[SP_MON_OBJ_ARM_DATA] +
479*e65e175bSOded Gabbay i * sizeof(u32));
480*e65e175bSOded Gabbay
481*e65e175bSOded Gabbay monitors[i].status =
482*e65e175bSOded Gabbay RREG32(base_addr + sds->props[SP_MON_OBJ_STATUS] +
483*e65e175bSOded Gabbay i * sizeof(u32));
484*e65e175bSOded Gabbay }
485*e65e175bSOded Gabbay
486*e65e175bSOded Gabbay return monitors;
487*e65e175bSOded Gabbay }
488*e65e175bSOded Gabbay
489*e65e175bSOded Gabbay /**
490*e65e175bSOded Gabbay * hl_state_dump_free_monitors - free the monitors structure
491*e65e175bSOded Gabbay * @monitors: monitors array created with
492*e65e175bSOded Gabbay * hl_state_dump_alloc_read_sm_block_monitors
493*e65e175bSOded Gabbay */
hl_state_dump_free_monitors(struct hl_mon_state_dump * monitors)494*e65e175bSOded Gabbay static void hl_state_dump_free_monitors(struct hl_mon_state_dump *monitors)
495*e65e175bSOded Gabbay {
496*e65e175bSOded Gabbay vfree(monitors);
497*e65e175bSOded Gabbay }
498*e65e175bSOded Gabbay
499*e65e175bSOded Gabbay /**
500*e65e175bSOded Gabbay * hl_state_dump_print_monitors_single_block - print active monitors on a
501*e65e175bSOded Gabbay * single block
502*e65e175bSOded Gabbay * @hdev: pointer to the device
503*e65e175bSOded Gabbay * @index: sync manager block index starting with E_N
504*e65e175bSOded Gabbay * @buf: destination buffer double pointer to be used with hl_snprintf_resize
505*e65e175bSOded Gabbay * @size: pointer to the size container
506*e65e175bSOded Gabbay * @offset: pointer to the offset container
507*e65e175bSOded Gabbay *
508*e65e175bSOded Gabbay * Returns 0 on success or error code on failure
509*e65e175bSOded Gabbay */
hl_state_dump_print_monitors_single_block(struct hl_device * hdev,u32 index,char ** buf,size_t * size,size_t * offset)510*e65e175bSOded Gabbay static int hl_state_dump_print_monitors_single_block(struct hl_device *hdev,
511*e65e175bSOded Gabbay u32 index,
512*e65e175bSOded Gabbay char **buf, size_t *size,
513*e65e175bSOded Gabbay size_t *offset)
514*e65e175bSOded Gabbay {
515*e65e175bSOded Gabbay struct hl_state_dump_specs *sds = &hdev->state_dump_specs;
516*e65e175bSOded Gabbay struct hl_mon_state_dump *monitors = NULL;
517*e65e175bSOded Gabbay int rc = 0, i;
518*e65e175bSOded Gabbay
519*e65e175bSOded Gabbay if (sds->sync_namager_names) {
520*e65e175bSOded Gabbay rc = hl_snprintf_resize(
521*e65e175bSOded Gabbay buf, size, offset, "%s\n",
522*e65e175bSOded Gabbay sds->sync_namager_names[index]);
523*e65e175bSOded Gabbay if (rc)
524*e65e175bSOded Gabbay goto out;
525*e65e175bSOded Gabbay }
526*e65e175bSOded Gabbay
527*e65e175bSOded Gabbay monitors = hl_state_dump_alloc_read_sm_block_monitors(hdev, index);
528*e65e175bSOded Gabbay if (!monitors) {
529*e65e175bSOded Gabbay rc = -ENOMEM;
530*e65e175bSOded Gabbay goto out;
531*e65e175bSOded Gabbay }
532*e65e175bSOded Gabbay
533*e65e175bSOded Gabbay for (i = 0; i < sds->props[SP_MONITORS_AMOUNT]; ++i) {
534*e65e175bSOded Gabbay if (!(sds->funcs.monitor_valid(&monitors[i])))
535*e65e175bSOded Gabbay continue;
536*e65e175bSOded Gabbay
537*e65e175bSOded Gabbay /* Monitor is valid, dump it */
538*e65e175bSOded Gabbay rc = sds->funcs.print_single_monitor(buf, size, offset, hdev,
539*e65e175bSOded Gabbay &monitors[i]);
540*e65e175bSOded Gabbay if (rc)
541*e65e175bSOded Gabbay goto free_monitors;
542*e65e175bSOded Gabbay
543*e65e175bSOded Gabbay hl_snprintf_resize(buf, size, offset, "\n");
544*e65e175bSOded Gabbay }
545*e65e175bSOded Gabbay
546*e65e175bSOded Gabbay free_monitors:
547*e65e175bSOded Gabbay hl_state_dump_free_monitors(monitors);
548*e65e175bSOded Gabbay out:
549*e65e175bSOded Gabbay return rc;
550*e65e175bSOded Gabbay }
551*e65e175bSOded Gabbay
552*e65e175bSOded Gabbay /**
553*e65e175bSOded Gabbay * hl_state_dump_print_monitors - print active monitors
554*e65e175bSOded Gabbay * @hdev: pointer to the device
555*e65e175bSOded Gabbay * @buf: destination buffer double pointer to be used with hl_snprintf_resize
556*e65e175bSOded Gabbay * @size: pointer to the size container
557*e65e175bSOded Gabbay * @offset: pointer to the offset container
558*e65e175bSOded Gabbay *
559*e65e175bSOded Gabbay * Returns 0 on success or error code on failure
560*e65e175bSOded Gabbay */
hl_state_dump_print_monitors(struct hl_device * hdev,char ** buf,size_t * size,size_t * offset)561*e65e175bSOded Gabbay static int hl_state_dump_print_monitors(struct hl_device *hdev,
562*e65e175bSOded Gabbay char **buf, size_t *size,
563*e65e175bSOded Gabbay size_t *offset)
564*e65e175bSOded Gabbay {
565*e65e175bSOded Gabbay struct hl_state_dump_specs *sds = &hdev->state_dump_specs;
566*e65e175bSOded Gabbay u32 index;
567*e65e175bSOded Gabbay int rc = 0;
568*e65e175bSOded Gabbay
569*e65e175bSOded Gabbay rc = hl_snprintf_resize(buf, size, offset,
570*e65e175bSOded Gabbay "Valid (armed) monitor objects:\n");
571*e65e175bSOded Gabbay if (rc)
572*e65e175bSOded Gabbay goto out;
573*e65e175bSOded Gabbay
574*e65e175bSOded Gabbay if (sds->sync_namager_names) {
575*e65e175bSOded Gabbay for (index = 0; sds->sync_namager_names[index]; ++index) {
576*e65e175bSOded Gabbay rc = hl_state_dump_print_monitors_single_block(
577*e65e175bSOded Gabbay hdev, index, buf, size, offset);
578*e65e175bSOded Gabbay if (rc)
579*e65e175bSOded Gabbay goto out;
580*e65e175bSOded Gabbay }
581*e65e175bSOded Gabbay } else {
582*e65e175bSOded Gabbay for (index = 0; index < sds->props[SP_NUM_CORES]; ++index) {
583*e65e175bSOded Gabbay rc = hl_state_dump_print_monitors_single_block(
584*e65e175bSOded Gabbay hdev, index, buf, size, offset);
585*e65e175bSOded Gabbay if (rc)
586*e65e175bSOded Gabbay goto out;
587*e65e175bSOded Gabbay }
588*e65e175bSOded Gabbay }
589*e65e175bSOded Gabbay
590*e65e175bSOded Gabbay out:
591*e65e175bSOded Gabbay return rc;
592*e65e175bSOded Gabbay }
593*e65e175bSOded Gabbay
594*e65e175bSOded Gabbay /**
595*e65e175bSOded Gabbay * hl_state_dump_print_engine_fences - print active fences for a specific
596*e65e175bSOded Gabbay * engine
597*e65e175bSOded Gabbay * @hdev: pointer to the device
598*e65e175bSOded Gabbay * @engine_type: engine type to use
599*e65e175bSOded Gabbay * @buf: destination buffer double pointer to be used with hl_snprintf_resize
600*e65e175bSOded Gabbay * @size: pointer to the size container
601*e65e175bSOded Gabbay * @offset: pointer to the offset container
602*e65e175bSOded Gabbay */
603*e65e175bSOded Gabbay static int
hl_state_dump_print_engine_fences(struct hl_device * hdev,enum hl_sync_engine_type engine_type,char ** buf,size_t * size,size_t * offset)604*e65e175bSOded Gabbay hl_state_dump_print_engine_fences(struct hl_device *hdev,
605*e65e175bSOded Gabbay enum hl_sync_engine_type engine_type,
606*e65e175bSOded Gabbay char **buf, size_t *size, size_t *offset)
607*e65e175bSOded Gabbay {
608*e65e175bSOded Gabbay struct hl_state_dump_specs *sds = &hdev->state_dump_specs;
609*e65e175bSOded Gabbay int rc = 0, i, n_fences;
610*e65e175bSOded Gabbay u64 base_addr, next_fence;
611*e65e175bSOded Gabbay
612*e65e175bSOded Gabbay switch (engine_type) {
613*e65e175bSOded Gabbay case ENGINE_TPC:
614*e65e175bSOded Gabbay n_fences = sds->props[SP_NUM_OF_TPC_ENGINES];
615*e65e175bSOded Gabbay base_addr = sds->props[SP_TPC0_CMDQ];
616*e65e175bSOded Gabbay next_fence = sds->props[SP_NEXT_TPC];
617*e65e175bSOded Gabbay break;
618*e65e175bSOded Gabbay case ENGINE_MME:
619*e65e175bSOded Gabbay n_fences = sds->props[SP_NUM_OF_MME_ENGINES];
620*e65e175bSOded Gabbay base_addr = sds->props[SP_MME_CMDQ];
621*e65e175bSOded Gabbay next_fence = sds->props[SP_NEXT_MME];
622*e65e175bSOded Gabbay break;
623*e65e175bSOded Gabbay case ENGINE_DMA:
624*e65e175bSOded Gabbay n_fences = sds->props[SP_NUM_OF_DMA_ENGINES];
625*e65e175bSOded Gabbay base_addr = sds->props[SP_DMA_CMDQ];
626*e65e175bSOded Gabbay next_fence = sds->props[SP_DMA_QUEUES_OFFSET];
627*e65e175bSOded Gabbay break;
628*e65e175bSOded Gabbay default:
629*e65e175bSOded Gabbay return -EINVAL;
630*e65e175bSOded Gabbay }
631*e65e175bSOded Gabbay for (i = 0; i < n_fences; ++i) {
632*e65e175bSOded Gabbay rc = sds->funcs.print_fences_single_engine(
633*e65e175bSOded Gabbay hdev,
634*e65e175bSOded Gabbay base_addr + next_fence * i +
635*e65e175bSOded Gabbay sds->props[SP_FENCE0_CNT_OFFSET],
636*e65e175bSOded Gabbay base_addr + next_fence * i +
637*e65e175bSOded Gabbay sds->props[SP_CP_STS_OFFSET],
638*e65e175bSOded Gabbay engine_type, i, buf, size, offset);
639*e65e175bSOded Gabbay if (rc)
640*e65e175bSOded Gabbay goto out;
641*e65e175bSOded Gabbay }
642*e65e175bSOded Gabbay out:
643*e65e175bSOded Gabbay return rc;
644*e65e175bSOded Gabbay }
645*e65e175bSOded Gabbay
646*e65e175bSOded Gabbay /**
647*e65e175bSOded Gabbay * hl_state_dump_print_fences - print active fences
648*e65e175bSOded Gabbay * @hdev: pointer to the device
649*e65e175bSOded Gabbay * @buf: destination buffer double pointer to be used with hl_snprintf_resize
650*e65e175bSOded Gabbay * @size: pointer to the size container
651*e65e175bSOded Gabbay * @offset: pointer to the offset container
652*e65e175bSOded Gabbay */
hl_state_dump_print_fences(struct hl_device * hdev,char ** buf,size_t * size,size_t * offset)653*e65e175bSOded Gabbay static int hl_state_dump_print_fences(struct hl_device *hdev, char **buf,
654*e65e175bSOded Gabbay size_t *size, size_t *offset)
655*e65e175bSOded Gabbay {
656*e65e175bSOded Gabbay int rc = 0;
657*e65e175bSOded Gabbay
658*e65e175bSOded Gabbay rc = hl_snprintf_resize(buf, size, offset, "Valid (armed) fences:\n");
659*e65e175bSOded Gabbay if (rc)
660*e65e175bSOded Gabbay goto out;
661*e65e175bSOded Gabbay
662*e65e175bSOded Gabbay rc = hl_state_dump_print_engine_fences(hdev, ENGINE_TPC, buf, size, offset);
663*e65e175bSOded Gabbay if (rc)
664*e65e175bSOded Gabbay goto out;
665*e65e175bSOded Gabbay
666*e65e175bSOded Gabbay rc = hl_state_dump_print_engine_fences(hdev, ENGINE_MME, buf, size, offset);
667*e65e175bSOded Gabbay if (rc)
668*e65e175bSOded Gabbay goto out;
669*e65e175bSOded Gabbay
670*e65e175bSOded Gabbay rc = hl_state_dump_print_engine_fences(hdev, ENGINE_DMA, buf, size, offset);
671*e65e175bSOded Gabbay if (rc)
672*e65e175bSOded Gabbay goto out;
673*e65e175bSOded Gabbay
674*e65e175bSOded Gabbay out:
675*e65e175bSOded Gabbay return rc;
676*e65e175bSOded Gabbay }
677*e65e175bSOded Gabbay
678*e65e175bSOded Gabbay /**
679*e65e175bSOded Gabbay * hl_state_dump() - dump system state
680*e65e175bSOded Gabbay * @hdev: pointer to device structure
681*e65e175bSOded Gabbay */
hl_state_dump(struct hl_device * hdev)682*e65e175bSOded Gabbay int hl_state_dump(struct hl_device *hdev)
683*e65e175bSOded Gabbay {
684*e65e175bSOded Gabbay char *buf = NULL;
685*e65e175bSOded Gabbay size_t offset = 0, size = 0;
686*e65e175bSOded Gabbay int rc;
687*e65e175bSOded Gabbay
688*e65e175bSOded Gabbay rc = hl_snprintf_resize(&buf, &size, &offset,
689*e65e175bSOded Gabbay "Timestamp taken on: %llu\n\n",
690*e65e175bSOded Gabbay ktime_to_ns(ktime_get()));
691*e65e175bSOded Gabbay if (rc)
692*e65e175bSOded Gabbay goto err;
693*e65e175bSOded Gabbay
694*e65e175bSOded Gabbay rc = hl_state_dump_print_syncs(hdev, &buf, &size, &offset);
695*e65e175bSOded Gabbay if (rc)
696*e65e175bSOded Gabbay goto err;
697*e65e175bSOded Gabbay
698*e65e175bSOded Gabbay hl_snprintf_resize(&buf, &size, &offset, "\n");
699*e65e175bSOded Gabbay
700*e65e175bSOded Gabbay rc = hl_state_dump_print_monitors(hdev, &buf, &size, &offset);
701*e65e175bSOded Gabbay if (rc)
702*e65e175bSOded Gabbay goto err;
703*e65e175bSOded Gabbay
704*e65e175bSOded Gabbay hl_snprintf_resize(&buf, &size, &offset, "\n");
705*e65e175bSOded Gabbay
706*e65e175bSOded Gabbay rc = hl_state_dump_print_fences(hdev, &buf, &size, &offset);
707*e65e175bSOded Gabbay if (rc)
708*e65e175bSOded Gabbay goto err;
709*e65e175bSOded Gabbay
710*e65e175bSOded Gabbay hl_snprintf_resize(&buf, &size, &offset, "\n");
711*e65e175bSOded Gabbay
712*e65e175bSOded Gabbay hl_debugfs_set_state_dump(hdev, buf, size);
713*e65e175bSOded Gabbay
714*e65e175bSOded Gabbay return 0;
715*e65e175bSOded Gabbay err:
716*e65e175bSOded Gabbay vfree(buf);
717*e65e175bSOded Gabbay return rc;
718*e65e175bSOded Gabbay }
719