xref: /linux/drivers/gpu/drm/xe/xe_assert.h (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
1 /* SPDX-License-Identifier: MIT */
2 /*
3  * Copyright © 2023 Intel Corporation
4  */
5 
6 #ifndef _XE_ASSERT_H_
7 #define _XE_ASSERT_H_
8 
9 #include <linux/string_helpers.h>
10 
11 #include <drm/drm_print.h>
12 
13 #include "xe_device_types.h"
14 #include "xe_step.h"
15 
16 /**
17  * DOC: Xe ASSERTs
18  *
19  * While Xe driver aims to be simpler than legacy i915 driver it is still
20  * complex enough that some changes introduced while adding new functionality
21  * could break the existing code.
22  *
23  * Adding &drm_WARN or &drm_err to catch unwanted programming usage could lead
24  * to undesired increased driver footprint and may impact production driver
25  * performance as this additional code will be always present.
26  *
27  * To allow annotate functions with additional detailed debug checks to assert
28  * that all prerequisites are satisfied, without worrying about footprint or
29  * performance penalty on production builds where all potential misuses
30  * introduced during code integration were already fixed, we introduce family
31  * of Xe assert macros that try to follow classic assert() utility:
32  *
33  *  * xe_assert()
34  *  * xe_tile_assert()
35  *  * xe_gt_assert()
36  *
37  * These macros are implemented on top of &drm_WARN, but unlikely to the origin,
38  * warning is triggered when provided condition is false. Additionally all above
39  * assert macros cannot be used in expressions or as a condition, since
40  * underlying code will be compiled out on non-debug builds.
41  *
42  * Note that these macros are not intended for use to cover known gaps in the
43  * implementation; for such cases use regular &drm_WARN or &drm_err and provide
44  * valid safe fallback.
45  *
46  * Also in cases where performance or footprint is not an issue, developers
47  * should continue to use the regular &drm_WARN or &drm_err to ensure that bug
48  * reports from production builds will contain meaningful diagnostics data.
49  *
50  * Below code shows how asserts could help in debug to catch unplanned use::
51  *
52  *	static void one_igfx(struct xe_device *xe)
53  *	{
54  *		xe_assert(xe, xe->info.is_dgfx == false);
55  *		xe_assert(xe, xe->info.tile_count == 1);
56  *	}
57  *
58  *	static void two_dgfx(struct xe_device *xe)
59  *	{
60  *		xe_assert(xe, xe->info.is_dgfx);
61  *		xe_assert(xe, xe->info.tile_count == 2);
62  *	}
63  *
64  *	void foo(struct xe_device *xe)
65  *	{
66  *		if (xe->info.dgfx)
67  *			return two_dgfx(xe);
68  *		return one_igfx(xe);
69  *	}
70  *
71  *	void bar(struct xe_device *xe)
72  *	{
73  *		if (drm_WARN_ON(xe->drm, xe->info.tile_count > 2))
74  *			return;
75  *
76  *		if (xe->info.tile_count == 2)
77  *			return two_dgfx(xe);
78  *		return one_igfx(xe);
79  *	}
80  */
81 
82 #if IS_ENABLED(CONFIG_DRM_XE_DEBUG)
83 #define __xe_assert_msg(xe, condition, msg, arg...) ({						\
84 	(void)drm_WARN(&(xe)->drm, !(condition), "Assertion `%s` failed!\n" msg,		\
85 		       __stringify(condition), ## arg);						\
86 })
87 #else
88 #define __xe_assert_msg(xe, condition, msg, arg...) ({						\
89 	typecheck(const struct xe_device *, xe);						\
90 	BUILD_BUG_ON_INVALID(condition);							\
91 })
92 #endif
93 
94 /**
95  * xe_assert - warn if condition is false when debugging.
96  * @xe: the &struct xe_device pointer to which &condition applies
97  * @condition: condition to check
98  *
99  * xe_assert() uses &drm_WARN to emit a warning and print additional information
100  * that could be read from the &xe pointer if provided &condition is false.
101  *
102  * Contrary to &drm_WARN, xe_assert() is effective only on debug builds
103  * (&CONFIG_DRM_XE_DEBUG must be enabled) and cannot be used in expressions
104  * or as a condition.
105  *
106  * See `Xe ASSERTs`_ for general usage guidelines.
107  */
108 #define xe_assert(xe, condition) xe_assert_msg((xe), condition, "")
109 #define xe_assert_msg(xe, condition, msg, arg...) ({						\
110 	const struct xe_device *__xe = (xe);							\
111 	__xe_assert_msg(__xe, condition,							\
112 			"platform: %s subplatform: %d\n"					\
113 			"graphics: %s %u.%02u step %s\n"					\
114 			"media: %s %u.%02u step %s\n"						\
115 			msg,									\
116 			__xe->info.platform_name, __xe->info.subplatform,			\
117 			__xe->info.graphics_name,						\
118 			__xe->info.graphics_verx100 / 100,					\
119 			__xe->info.graphics_verx100 % 100,					\
120 			xe_step_name(__xe->info.step.graphics),					\
121 			__xe->info.media_name,							\
122 			__xe->info.media_verx100 / 100,						\
123 			__xe->info.media_verx100 % 100,						\
124 			xe_step_name(__xe->info.step.media),					\
125 			## arg);								\
126 })
127 
128 /**
129  * xe_tile_assert - warn if condition is false when debugging.
130  * @tile: the &struct xe_tile pointer to which &condition applies
131  * @condition: condition to check
132  *
133  * xe_tile_assert() uses &drm_WARN to emit a warning and print additional
134  * information that could be read from the &tile pointer if provided &condition
135  * is false.
136  *
137  * Contrary to &drm_WARN, xe_tile_assert() is effective only on debug builds
138  * (&CONFIG_DRM_XE_DEBUG must be enabled) and cannot be used in expressions
139  * or as a condition.
140  *
141  * See `Xe ASSERTs`_ for general usage guidelines.
142  */
143 #define xe_tile_assert(tile, condition) xe_tile_assert_msg((tile), condition, "")
144 #define xe_tile_assert_msg(tile, condition, msg, arg...) ({					\
145 	const struct xe_tile *__tile = (tile);							\
146 	char __buf[10] __maybe_unused;								\
147 	xe_assert_msg(tile_to_xe(__tile), condition, "tile: %u VRAM %s\n" msg,			\
148 		      __tile->id, ({ string_get_size(__tile->mem.vram.actual_physical_size, 1,	\
149 				     STRING_UNITS_2, __buf, sizeof(__buf)); __buf; }), ## arg);	\
150 })
151 
152 /**
153  * xe_gt_assert - warn if condition is false when debugging.
154  * @gt: the &struct xe_gt pointer to which &condition applies
155  * @condition: condition to check
156  *
157  * xe_gt_assert() uses &drm_WARN to emit a warning and print additional
158  * information that could be safetely read from the &gt pointer if provided
159  * &condition is false.
160  *
161  * Contrary to &drm_WARN, xe_gt_assert() is effective only on debug builds
162  * (&CONFIG_DRM_XE_DEBUG must be enabled) and cannot be used in expressions
163  * or as a condition.
164  *
165  * See `Xe ASSERTs`_ for general usage guidelines.
166  */
167 #define xe_gt_assert(gt, condition) xe_gt_assert_msg((gt), condition, "")
168 #define xe_gt_assert_msg(gt, condition, msg, arg...) ({						\
169 	const struct xe_gt *__gt = (gt);							\
170 	xe_tile_assert_msg(gt_to_tile(__gt), condition, "GT: %u type %d\n" msg,			\
171 			   __gt->info.id, __gt->info.type, ## arg);				\
172 })
173 
174 #endif
175