xref: /openbmc/linux/drivers/gpu/drm/i915/i915_utils.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1358c855cSJani Nikula // SPDX-License-Identifier: MIT
2358c855cSJani Nikula /*
3358c855cSJani Nikula  * Copyright © 2019 Intel Corporation
4358c855cSJani Nikula  */
5358c855cSJani Nikula 
6*a7f46d5bSTvrtko Ursulin #include <linux/device.h>
7*a7f46d5bSTvrtko Ursulin 
8358c855cSJani Nikula #include <drm/drm_drv.h>
9358c855cSJani Nikula 
10358c855cSJani Nikula #include "i915_drv.h"
11358c855cSJani Nikula #include "i915_utils.h"
12358c855cSJani Nikula 
13ddae4d7aSJani Nikula #define FDO_BUG_MSG "Please file a bug on drm/i915; see " FDO_BUG_URL " for details."
14358c855cSJani Nikula 
15358c855cSJani Nikula void
__i915_printk(struct drm_i915_private * dev_priv,const char * level,const char * fmt,...)16358c855cSJani Nikula __i915_printk(struct drm_i915_private *dev_priv, const char *level,
17358c855cSJani Nikula 	      const char *fmt, ...)
18358c855cSJani Nikula {
19358c855cSJani Nikula 	static bool shown_bug_once;
20358c855cSJani Nikula 	struct device *kdev = dev_priv->drm.dev;
21358c855cSJani Nikula 	bool is_error = level[1] <= KERN_ERR[1];
22358c855cSJani Nikula 	bool is_debug = level[1] == KERN_DEBUG[1];
23358c855cSJani Nikula 	struct va_format vaf;
24358c855cSJani Nikula 	va_list args;
25358c855cSJani Nikula 
26bdbf43d7SJani Nikula 	if (is_debug && !drm_debug_enabled(DRM_UT_DRIVER))
27358c855cSJani Nikula 		return;
28358c855cSJani Nikula 
29358c855cSJani Nikula 	va_start(args, fmt);
30358c855cSJani Nikula 
31358c855cSJani Nikula 	vaf.fmt = fmt;
32358c855cSJani Nikula 	vaf.va = &args;
33358c855cSJani Nikula 
34358c855cSJani Nikula 	if (is_error)
35358c855cSJani Nikula 		dev_printk(level, kdev, "%pV", &vaf);
36358c855cSJani Nikula 	else
37358c855cSJani Nikula 		dev_printk(level, kdev, "[" DRM_NAME ":%ps] %pV",
38358c855cSJani Nikula 			   __builtin_return_address(0), &vaf);
39358c855cSJani Nikula 
40358c855cSJani Nikula 	va_end(args);
41358c855cSJani Nikula 
42358c855cSJani Nikula 	if (is_error && !shown_bug_once) {
43358c855cSJani Nikula 		/*
44358c855cSJani Nikula 		 * Ask the user to file a bug report for the error, except
45358c855cSJani Nikula 		 * if they may have caused the bug by fiddling with unsafe
46358c855cSJani Nikula 		 * module parameters.
47358c855cSJani Nikula 		 */
48358c855cSJani Nikula 		if (!test_taint(TAINT_USER))
49358c855cSJani Nikula 			dev_notice(kdev, "%s", FDO_BUG_MSG);
50358c855cSJani Nikula 		shown_bug_once = true;
51358c855cSJani Nikula 	}
52358c855cSJani Nikula }
53358c855cSJani Nikula 
add_taint_for_CI(struct drm_i915_private * i915,unsigned int taint)5465706203SMichał Winiarski void add_taint_for_CI(struct drm_i915_private *i915, unsigned int taint)
5565706203SMichał Winiarski {
5665706203SMichał Winiarski 	__i915_printk(i915, KERN_NOTICE, "CI tainted:%#x by %pS\n",
5765706203SMichał Winiarski 		      taint, (void *)_RET_IP_);
58fcab594aSMichał Winiarski 
59fcab594aSMichał Winiarski 	/* Failures that occur during fault injection testing are expected */
60fcab594aSMichał Winiarski 	if (!i915_error_injected())
6165706203SMichał Winiarski 		__add_taint_for_CI(taint);
6265706203SMichał Winiarski }
6365706203SMichał Winiarski 
64358c855cSJani Nikula #if IS_ENABLED(CONFIG_DRM_I915_DEBUG)
65358c855cSJani Nikula static unsigned int i915_probe_fail_count;
66358c855cSJani Nikula 
__i915_inject_probe_error(struct drm_i915_private * i915,int err,const char * func,int line)67dd6e38dfSJanusz Krzysztofik int __i915_inject_probe_error(struct drm_i915_private *i915, int err,
68358c855cSJani Nikula 			      const char *func, int line)
69358c855cSJani Nikula {
704ec37538SJanusz Krzysztofik 	if (i915_probe_fail_count >= i915_modparams.inject_probe_failure)
71358c855cSJani Nikula 		return 0;
72358c855cSJani Nikula 
734ec37538SJanusz Krzysztofik 	if (++i915_probe_fail_count < i915_modparams.inject_probe_failure)
74358c855cSJani Nikula 		return 0;
75358c855cSJani Nikula 
76358c855cSJani Nikula 	__i915_printk(i915, KERN_INFO,
77358c855cSJani Nikula 		      "Injecting failure %d at checkpoint %u [%s:%d]\n",
784ec37538SJanusz Krzysztofik 		      err, i915_modparams.inject_probe_failure, func, line);
794ec37538SJanusz Krzysztofik 	i915_modparams.inject_probe_failure = 0;
80358c855cSJani Nikula 	return err;
81358c855cSJani Nikula }
82358c855cSJani Nikula 
i915_error_injected(void)83358c855cSJani Nikula bool i915_error_injected(void)
84358c855cSJani Nikula {
854ec37538SJanusz Krzysztofik 	return i915_probe_fail_count && !i915_modparams.inject_probe_failure;
86358c855cSJani Nikula }
87358c855cSJani Nikula 
88358c855cSJani Nikula #endif
893a7a92abSChris Wilson 
cancel_timer(struct timer_list * t)903a7a92abSChris Wilson void cancel_timer(struct timer_list *t)
913a7a92abSChris Wilson {
92c185a16eSChris Wilson 	if (!timer_active(t))
933a7a92abSChris Wilson 		return;
943a7a92abSChris Wilson 
953a7a92abSChris Wilson 	del_timer(t);
963a7a92abSChris Wilson 	WRITE_ONCE(t->expires, 0);
973a7a92abSChris Wilson }
983a7a92abSChris Wilson 
set_timer_ms(struct timer_list * t,unsigned long timeout)993a7a92abSChris Wilson void set_timer_ms(struct timer_list *t, unsigned long timeout)
1003a7a92abSChris Wilson {
1013a7a92abSChris Wilson 	if (!timeout) {
1023a7a92abSChris Wilson 		cancel_timer(t);
1033a7a92abSChris Wilson 		return;
1043a7a92abSChris Wilson 	}
1053a7a92abSChris Wilson 
106f4bb45f7SChris Wilson 	timeout = msecs_to_jiffies(timeout);
1073a7a92abSChris Wilson 
1083a7a92abSChris Wilson 	/*
1093a7a92abSChris Wilson 	 * Paranoia to make sure the compiler computes the timeout before
1103a7a92abSChris Wilson 	 * loading 'jiffies' as jiffies is volatile and may be updated in
1113a7a92abSChris Wilson 	 * the background by a timer tick. All to reduce the complexity
1123a7a92abSChris Wilson 	 * of the addition and reduce the risk of losing a jiffie.
1133a7a92abSChris Wilson 	 */
1143a7a92abSChris Wilson 	barrier();
1153a7a92abSChris Wilson 
116bfae03feSChris Wilson 	/* Keep t->expires = 0 reserved to indicate a canceled timer. */
117bfae03feSChris Wilson 	mod_timer(t, jiffies + timeout ?: 1);
1183a7a92abSChris Wilson }
119*a7f46d5bSTvrtko Ursulin 
i915_vtd_active(struct drm_i915_private * i915)120*a7f46d5bSTvrtko Ursulin bool i915_vtd_active(struct drm_i915_private *i915)
121*a7f46d5bSTvrtko Ursulin {
122*a7f46d5bSTvrtko Ursulin 	if (device_iommu_mapped(i915->drm.dev))
123*a7f46d5bSTvrtko Ursulin 		return true;
124*a7f46d5bSTvrtko Ursulin 
125*a7f46d5bSTvrtko Ursulin 	/* Running as a guest, we assume the host is enforcing VT'd */
126*a7f46d5bSTvrtko Ursulin 	return i915_run_as_guest();
127*a7f46d5bSTvrtko Ursulin }
128