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