xref: /openbmc/linux/drivers/accel/habanalabs/common/state_dump.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
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