Commit 4fec15d1 authored by Imre Deak's avatar Imre Deak

drm/i915: Add fault injection support

Add support for forcing an error at selected places in the driver. As an
example add 4 options to fail during driver loading.

Requested by Chris.

v2:
- Add fault point for modeset initialization
- Print debug message when injecting an error
v3:
- Rename inject_fault to inject_load_failure, rename the related macros
  and helper accordingly (Chris)
- Use a counter instead of a mask to identify the failure point (Daniel)
- Mark the module option as _unsafe and keep i915_params ordered (Joonas)
v4:
- Rebase on latest -nightly
v5:
- Use DRM_INFO instead of DRM_DEBUG_DRIVER, making it clearer in CI reports
  that a following error message is expected (IRC r-b from Chris on v5)

CC: Chris Wilson <chris@chris-wilson.co.uk>
CC: Daniel Vetter <daniel.vetter@ffwll.ch>
CC: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: default avatarImre Deak <imre.deak@intel.com>
Reviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
parent 65ff442f
...@@ -50,6 +50,21 @@ ...@@ -50,6 +50,21 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/oom.h> #include <linux/oom.h>
static unsigned int i915_load_fail_count;
bool __i915_inject_load_failure(const char *func, int line)
{
if (i915_load_fail_count >= i915.inject_load_failure)
return false;
if (++i915_load_fail_count == i915.inject_load_failure) {
DRM_INFO("Injecting failure at checkpoint %u [%s:%d]\n",
i915.inject_load_failure, func, line);
return true;
}
return false;
}
static int i915_getparam(struct drm_device *dev, void *data, static int i915_getparam(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
...@@ -370,6 +385,9 @@ static int i915_load_modeset_init(struct drm_device *dev) ...@@ -370,6 +385,9 @@ static int i915_load_modeset_init(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
int ret; int ret;
if (i915_inject_load_failure())
return -ENODEV;
ret = intel_bios_init(dev_priv); ret = intel_bios_init(dev_priv);
if (ret) if (ret)
DRM_INFO("failed to find VBIOS tables\n"); DRM_INFO("failed to find VBIOS tables\n");
...@@ -951,6 +969,9 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, ...@@ -951,6 +969,9 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
struct intel_device_info *device_info; struct intel_device_info *device_info;
int ret = 0; int ret = 0;
if (i915_inject_load_failure())
return -ENODEV;
dev_priv->dev = dev; dev_priv->dev = dev;
/* Setup the write-once "constant" device info */ /* Setup the write-once "constant" device info */
...@@ -1065,6 +1086,9 @@ static int i915_driver_init_mmio(struct drm_i915_private *dev_priv) ...@@ -1065,6 +1086,9 @@ static int i915_driver_init_mmio(struct drm_i915_private *dev_priv)
struct drm_device *dev = dev_priv->dev; struct drm_device *dev = dev_priv->dev;
int ret; int ret;
if (i915_inject_load_failure())
return -ENODEV;
if (i915_get_bridge_dev(dev)) if (i915_get_bridge_dev(dev))
return -EIO; return -EIO;
...@@ -1108,6 +1132,9 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) ...@@ -1108,6 +1132,9 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
uint32_t aperture_size; uint32_t aperture_size;
int ret; int ret;
if (i915_inject_load_failure())
return -ENODEV;
intel_device_info_runtime_init(dev); intel_device_info_runtime_init(dev);
ret = i915_gem_gtt_init(dev); ret = i915_gem_gtt_init(dev);
......
...@@ -98,6 +98,10 @@ ...@@ -98,6 +98,10 @@
#define I915_STATE_WARN_ON(x) \ #define I915_STATE_WARN_ON(x) \
I915_STATE_WARN((x), "%s", "WARN_ON(" __stringify(x) ")") I915_STATE_WARN((x), "%s", "WARN_ON(" __stringify(x) ")")
bool __i915_inject_load_failure(const char *func, int line);
#define i915_inject_load_failure() \
__i915_inject_load_failure(__func__, __LINE__)
static inline const char *yesno(bool v) static inline const char *yesno(bool v)
{ {
return v ? "yes" : "no"; return v ? "yes" : "no";
......
...@@ -57,6 +57,7 @@ struct i915_params i915 __read_mostly = { ...@@ -57,6 +57,7 @@ struct i915_params i915 __read_mostly = {
.enable_guc_submission = false, .enable_guc_submission = false,
.guc_log_level = -1, .guc_log_level = -1,
.enable_dp_mst = true, .enable_dp_mst = true,
.inject_load_failure = 0,
}; };
module_param_named(modeset, i915.modeset, int, 0400); module_param_named(modeset, i915.modeset, int, 0400);
...@@ -206,3 +207,6 @@ MODULE_PARM_DESC(guc_log_level, ...@@ -206,3 +207,6 @@ MODULE_PARM_DESC(guc_log_level,
module_param_named_unsafe(enable_dp_mst, i915.enable_dp_mst, bool, 0600); module_param_named_unsafe(enable_dp_mst, i915.enable_dp_mst, bool, 0600);
MODULE_PARM_DESC(enable_dp_mst, MODULE_PARM_DESC(enable_dp_mst,
"Enable multi-stream transport (MST) for new DisplayPort sinks. (default: true)"); "Enable multi-stream transport (MST) for new DisplayPort sinks. (default: true)");
module_param_named_unsafe(inject_load_failure, i915.inject_load_failure, uint, 0400);
MODULE_PARM_DESC(inject_load_failure,
"Force an error after a number of failure check points (0:disabled (default), N:force failure at the Nth failure check point)");
...@@ -49,6 +49,7 @@ struct i915_params { ...@@ -49,6 +49,7 @@ struct i915_params {
int use_mmio_flip; int use_mmio_flip;
int mmio_debug; int mmio_debug;
int edp_vswing; int edp_vswing;
unsigned int inject_load_failure;
/* leave bools at the end to not create holes */ /* leave bools at the end to not create holes */
bool enable_hangcheck; bool enable_hangcheck;
bool fastboot; bool fastboot;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment