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: Imre Deak <imre.deak@intel.com> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
parent
65ff442f6b
commit
4fec15d1bd
|
@ -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)
|
||||||
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,
|
||||||
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)
|
||||||
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)
|
||||||
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 @@
|
||||||
#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 = {
|
||||||
.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,
|
||||||
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 {
|
||||||
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;
|
||||||
|
|
Loading…
Reference in New Issue