162306a36Sopenharmony_ci// SPDX-License-Identifier: MIT
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright © 2019 Intel Corporation
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/device.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <drm/drm_drv.h>
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include "i915_drv.h"
1162306a36Sopenharmony_ci#include "i915_utils.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#define FDO_BUG_MSG "Please file a bug on drm/i915; see " FDO_BUG_URL " for details."
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_civoid
1662306a36Sopenharmony_ci__i915_printk(struct drm_i915_private *dev_priv, const char *level,
1762306a36Sopenharmony_ci	      const char *fmt, ...)
1862306a36Sopenharmony_ci{
1962306a36Sopenharmony_ci	static bool shown_bug_once;
2062306a36Sopenharmony_ci	struct device *kdev = dev_priv->drm.dev;
2162306a36Sopenharmony_ci	bool is_error = level[1] <= KERN_ERR[1];
2262306a36Sopenharmony_ci	bool is_debug = level[1] == KERN_DEBUG[1];
2362306a36Sopenharmony_ci	struct va_format vaf;
2462306a36Sopenharmony_ci	va_list args;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	if (is_debug && !drm_debug_enabled(DRM_UT_DRIVER))
2762306a36Sopenharmony_ci		return;
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	va_start(args, fmt);
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	vaf.fmt = fmt;
3262306a36Sopenharmony_ci	vaf.va = &args;
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	if (is_error)
3562306a36Sopenharmony_ci		dev_printk(level, kdev, "%pV", &vaf);
3662306a36Sopenharmony_ci	else
3762306a36Sopenharmony_ci		dev_printk(level, kdev, "[" DRM_NAME ":%ps] %pV",
3862306a36Sopenharmony_ci			   __builtin_return_address(0), &vaf);
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	va_end(args);
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	if (is_error && !shown_bug_once) {
4362306a36Sopenharmony_ci		/*
4462306a36Sopenharmony_ci		 * Ask the user to file a bug report for the error, except
4562306a36Sopenharmony_ci		 * if they may have caused the bug by fiddling with unsafe
4662306a36Sopenharmony_ci		 * module parameters.
4762306a36Sopenharmony_ci		 */
4862306a36Sopenharmony_ci		if (!test_taint(TAINT_USER))
4962306a36Sopenharmony_ci			dev_notice(kdev, "%s", FDO_BUG_MSG);
5062306a36Sopenharmony_ci		shown_bug_once = true;
5162306a36Sopenharmony_ci	}
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_civoid add_taint_for_CI(struct drm_i915_private *i915, unsigned int taint)
5562306a36Sopenharmony_ci{
5662306a36Sopenharmony_ci	__i915_printk(i915, KERN_NOTICE, "CI tainted:%#x by %pS\n",
5762306a36Sopenharmony_ci		      taint, (void *)_RET_IP_);
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	/* Failures that occur during fault injection testing are expected */
6062306a36Sopenharmony_ci	if (!i915_error_injected())
6162306a36Sopenharmony_ci		__add_taint_for_CI(taint);
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_DRM_I915_DEBUG)
6562306a36Sopenharmony_cistatic unsigned int i915_probe_fail_count;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ciint __i915_inject_probe_error(struct drm_i915_private *i915, int err,
6862306a36Sopenharmony_ci			      const char *func, int line)
6962306a36Sopenharmony_ci{
7062306a36Sopenharmony_ci	if (i915_probe_fail_count >= i915_modparams.inject_probe_failure)
7162306a36Sopenharmony_ci		return 0;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	if (++i915_probe_fail_count < i915_modparams.inject_probe_failure)
7462306a36Sopenharmony_ci		return 0;
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	__i915_printk(i915, KERN_INFO,
7762306a36Sopenharmony_ci		      "Injecting failure %d at checkpoint %u [%s:%d]\n",
7862306a36Sopenharmony_ci		      err, i915_modparams.inject_probe_failure, func, line);
7962306a36Sopenharmony_ci	i915_modparams.inject_probe_failure = 0;
8062306a36Sopenharmony_ci	return err;
8162306a36Sopenharmony_ci}
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_cibool i915_error_injected(void)
8462306a36Sopenharmony_ci{
8562306a36Sopenharmony_ci	return i915_probe_fail_count && !i915_modparams.inject_probe_failure;
8662306a36Sopenharmony_ci}
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci#endif
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_civoid cancel_timer(struct timer_list *t)
9162306a36Sopenharmony_ci{
9262306a36Sopenharmony_ci	if (!timer_active(t))
9362306a36Sopenharmony_ci		return;
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	del_timer(t);
9662306a36Sopenharmony_ci	WRITE_ONCE(t->expires, 0);
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_civoid set_timer_ms(struct timer_list *t, unsigned long timeout)
10062306a36Sopenharmony_ci{
10162306a36Sopenharmony_ci	if (!timeout) {
10262306a36Sopenharmony_ci		cancel_timer(t);
10362306a36Sopenharmony_ci		return;
10462306a36Sopenharmony_ci	}
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	timeout = msecs_to_jiffies(timeout);
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	/*
10962306a36Sopenharmony_ci	 * Paranoia to make sure the compiler computes the timeout before
11062306a36Sopenharmony_ci	 * loading 'jiffies' as jiffies is volatile and may be updated in
11162306a36Sopenharmony_ci	 * the background by a timer tick. All to reduce the complexity
11262306a36Sopenharmony_ci	 * of the addition and reduce the risk of losing a jiffie.
11362306a36Sopenharmony_ci	 */
11462306a36Sopenharmony_ci	barrier();
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	/* Keep t->expires = 0 reserved to indicate a canceled timer. */
11762306a36Sopenharmony_ci	mod_timer(t, jiffies + timeout ?: 1);
11862306a36Sopenharmony_ci}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_cibool i915_vtd_active(struct drm_i915_private *i915)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	if (device_iommu_mapped(i915->drm.dev))
12362306a36Sopenharmony_ci		return true;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	/* Running as a guest, we assume the host is enforcing VT'd */
12662306a36Sopenharmony_ci	return i915_run_as_guest();
12762306a36Sopenharmony_ci}
128