diff options
| author | Mark Brown <[email protected]> | 2015-10-12 18:09:27 +0100 | 
|---|---|---|
| committer | Mark Brown <[email protected]> | 2015-10-12 18:09:27 +0100 | 
| commit | 79828b4fa835f73cdaf4bffa48696abdcbea9d02 (patch) | |
| tree | 5e0fa7156acb75ba603022bc807df8f2fedb97a8 /drivers/gpu/drm/i915/intel_uncore.c | |
| parent | 721b51fcf91898299d96f4b72cb9434cda29dce6 (diff) | |
| parent | 8c1a9d6323abf0fb1e5dad96cf3f1c783505ea5a (diff) | |
Merge remote-tracking branch 'asoc/fix/rt5645' into asoc-fix-rt5645
Diffstat (limited to 'drivers/gpu/drm/i915/intel_uncore.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_uncore.c | 100 | 
1 files changed, 86 insertions, 14 deletions
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index a6d8a3ee7750..9d3c2e420d2b 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1274,10 +1274,12 @@ int i915_reg_read_ioctl(struct drm_device *dev,  	struct drm_i915_private *dev_priv = dev->dev_private;  	struct drm_i915_reg_read *reg = data;  	struct register_whitelist const *entry = whitelist; +	unsigned size; +	u64 offset;  	int i, ret = 0;  	for (i = 0; i < ARRAY_SIZE(whitelist); i++, entry++) { -		if (entry->offset == reg->offset && +		if (entry->offset == (reg->offset & -entry->size) &&  		    (1 << INTEL_INFO(dev)->gen & entry->gen_bitmask))  			break;  	} @@ -1285,23 +1287,33 @@ int i915_reg_read_ioctl(struct drm_device *dev,  	if (i == ARRAY_SIZE(whitelist))  		return -EINVAL; +	/* We use the low bits to encode extra flags as the register should +	 * be naturally aligned (and those that are not so aligned merely +	 * limit the available flags for that register). +	 */ +	offset = entry->offset; +	size = entry->size; +	size |= reg->offset ^ offset; +  	intel_runtime_pm_get(dev_priv); -	switch (entry->size) { +	switch (size) { +	case 8 | 1: +		reg->val = I915_READ64_2x32(offset, offset+4); +		break;  	case 8: -		reg->val = I915_READ64(reg->offset); +		reg->val = I915_READ64(offset);  		break;  	case 4: -		reg->val = I915_READ(reg->offset); +		reg->val = I915_READ(offset);  		break;  	case 2: -		reg->val = I915_READ16(reg->offset); +		reg->val = I915_READ16(offset);  		break;  	case 1: -		reg->val = I915_READ8(reg->offset); +		reg->val = I915_READ8(offset);  		break;  	default: -		MISSING_CASE(entry->size);  		ret = -EINVAL;  		goto out;  	} @@ -1455,20 +1467,80 @@ static int gen6_do_reset(struct drm_device *dev)  	return ret;  } -int intel_gpu_reset(struct drm_device *dev) +static int wait_for_register(struct drm_i915_private *dev_priv, +			     const u32 reg, +			     const u32 mask, +			     const u32 value, +			     const unsigned long timeout_ms) +{ +	return wait_for((I915_READ(reg) & mask) == value, timeout_ms); +} + +static int gen8_do_reset(struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	struct intel_engine_cs *engine; +	int i; + +	for_each_ring(engine, dev_priv, i) { +		I915_WRITE(RING_RESET_CTL(engine->mmio_base), +			   _MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET)); + +		if (wait_for_register(dev_priv, +				      RING_RESET_CTL(engine->mmio_base), +				      RESET_CTL_READY_TO_RESET, +				      RESET_CTL_READY_TO_RESET, +				      700)) { +			DRM_ERROR("%s: reset request timeout\n", engine->name); +			goto not_ready; +		} +	} + +	return gen6_do_reset(dev); + +not_ready: +	for_each_ring(engine, dev_priv, i) +		I915_WRITE(RING_RESET_CTL(engine->mmio_base), +			   _MASKED_BIT_DISABLE(RESET_CTL_REQUEST_RESET)); + +	return -EIO; +} + +static int (*intel_get_gpu_reset(struct drm_device *dev))(struct drm_device *)  { -	if (INTEL_INFO(dev)->gen >= 6) -		return gen6_do_reset(dev); +	if (!i915.reset) +		return NULL; + +	if (INTEL_INFO(dev)->gen >= 8) +		return gen8_do_reset; +	else if (INTEL_INFO(dev)->gen >= 6) +		return gen6_do_reset;  	else if (IS_GEN5(dev)) -		return ironlake_do_reset(dev); +		return ironlake_do_reset;  	else if (IS_G4X(dev)) -		return g4x_do_reset(dev); +		return g4x_do_reset;  	else if (IS_G33(dev)) -		return g33_do_reset(dev); +		return g33_do_reset;  	else if (INTEL_INFO(dev)->gen >= 3) -		return i915_do_reset(dev); +		return i915_do_reset;  	else +		return NULL; +} + +int intel_gpu_reset(struct drm_device *dev) +{ +	int (*reset)(struct drm_device *); + +	reset = intel_get_gpu_reset(dev); +	if (reset == NULL)  		return -ENODEV; + +	return reset(dev); +} + +bool intel_has_gpu_reset(struct drm_device *dev) +{ +	return intel_get_gpu_reset(dev) != NULL;  }  void intel_uncore_check_errors(struct drm_device *dev)  |