Merge tag 'pinctrl-v6.9-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw...
[linux-block.git] / drivers / gpu / drm / xe / xe_assert.h
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), "[" DRM_NAME "] 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: %d 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, __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