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