Merge tag 'drm-intel-fixes-2014-04-11' of git://anongit.freedesktop.org/drm-intel into drm-next
Some fixes from Intel. * tag 'drm-intel-fixes-2014-04-11' of git://anongit.freedesktop.org/drm-intel: drm/i915: Always use kref tracking for all contexts. drm/i915: do not setup backlight if not available according to VBT drm/i915: check VBT for supported backlight type drm/i915: Disable self-refresh for untiled fbs on i915gm drm/mm: Don't WARN if drm_mm_reserve_node
This commit is contained in:
commit
5df5242d34
|
@ -207,8 +207,6 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
WARN(1, "no hole found for node 0x%lx + 0x%lx\n",
|
|
||||||
node->start, node->size);
|
|
||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_mm_reserve_node);
|
EXPORT_SYMBOL(drm_mm_reserve_node);
|
||||||
|
|
|
@ -1308,6 +1308,7 @@ struct intel_vbt_data {
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
u16 pwm_freq_hz;
|
u16 pwm_freq_hz;
|
||||||
|
bool present;
|
||||||
bool active_low_pwm;
|
bool active_low_pwm;
|
||||||
} backlight;
|
} backlight;
|
||||||
|
|
||||||
|
@ -2431,20 +2432,18 @@ int i915_gem_context_open(struct drm_device *dev, struct drm_file *file);
|
||||||
int i915_gem_context_enable(struct drm_i915_private *dev_priv);
|
int i915_gem_context_enable(struct drm_i915_private *dev_priv);
|
||||||
void i915_gem_context_close(struct drm_device *dev, struct drm_file *file);
|
void i915_gem_context_close(struct drm_device *dev, struct drm_file *file);
|
||||||
int i915_switch_context(struct intel_ring_buffer *ring,
|
int i915_switch_context(struct intel_ring_buffer *ring,
|
||||||
struct drm_file *file, struct i915_hw_context *to);
|
struct i915_hw_context *to);
|
||||||
struct i915_hw_context *
|
struct i915_hw_context *
|
||||||
i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id);
|
i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id);
|
||||||
void i915_gem_context_free(struct kref *ctx_ref);
|
void i915_gem_context_free(struct kref *ctx_ref);
|
||||||
static inline void i915_gem_context_reference(struct i915_hw_context *ctx)
|
static inline void i915_gem_context_reference(struct i915_hw_context *ctx)
|
||||||
{
|
{
|
||||||
if (ctx->obj && HAS_HW_CONTEXTS(ctx->obj->base.dev))
|
kref_get(&ctx->ref);
|
||||||
kref_get(&ctx->ref);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void i915_gem_context_unreference(struct i915_hw_context *ctx)
|
static inline void i915_gem_context_unreference(struct i915_hw_context *ctx)
|
||||||
{
|
{
|
||||||
if (ctx->obj && HAS_HW_CONTEXTS(ctx->obj->base.dev))
|
kref_put(&ctx->ref, i915_gem_context_free);
|
||||||
kref_put(&ctx->ref, i915_gem_context_free);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool i915_gem_context_is_default(const struct i915_hw_context *c)
|
static inline bool i915_gem_context_is_default(const struct i915_hw_context *c)
|
||||||
|
|
|
@ -2790,7 +2790,7 @@ int i915_gpu_idle(struct drm_device *dev)
|
||||||
|
|
||||||
/* Flush everything onto the inactive list. */
|
/* Flush everything onto the inactive list. */
|
||||||
for_each_ring(ring, dev_priv, i) {
|
for_each_ring(ring, dev_priv, i) {
|
||||||
ret = i915_switch_context(ring, NULL, ring->default_context);
|
ret = i915_switch_context(ring, ring->default_context);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
|
@ -96,9 +96,6 @@
|
||||||
#define GEN6_CONTEXT_ALIGN (64<<10)
|
#define GEN6_CONTEXT_ALIGN (64<<10)
|
||||||
#define GEN7_CONTEXT_ALIGN 4096
|
#define GEN7_CONTEXT_ALIGN 4096
|
||||||
|
|
||||||
static int do_switch(struct intel_ring_buffer *ring,
|
|
||||||
struct i915_hw_context *to);
|
|
||||||
|
|
||||||
static void do_ppgtt_cleanup(struct i915_hw_ppgtt *ppgtt)
|
static void do_ppgtt_cleanup(struct i915_hw_ppgtt *ppgtt)
|
||||||
{
|
{
|
||||||
struct drm_device *dev = ppgtt->base.dev;
|
struct drm_device *dev = ppgtt->base.dev;
|
||||||
|
@ -185,13 +182,15 @@ void i915_gem_context_free(struct kref *ctx_ref)
|
||||||
typeof(*ctx), ref);
|
typeof(*ctx), ref);
|
||||||
struct i915_hw_ppgtt *ppgtt = NULL;
|
struct i915_hw_ppgtt *ppgtt = NULL;
|
||||||
|
|
||||||
/* We refcount even the aliasing PPGTT to keep the code symmetric */
|
if (ctx->obj) {
|
||||||
if (USES_PPGTT(ctx->obj->base.dev))
|
/* We refcount even the aliasing PPGTT to keep the code symmetric */
|
||||||
ppgtt = ctx_to_ppgtt(ctx);
|
if (USES_PPGTT(ctx->obj->base.dev))
|
||||||
|
ppgtt = ctx_to_ppgtt(ctx);
|
||||||
|
|
||||||
/* XXX: Free up the object before tearing down the address space, in
|
/* XXX: Free up the object before tearing down the address space, in
|
||||||
* case we're bound in the PPGTT */
|
* case we're bound in the PPGTT */
|
||||||
drm_gem_object_unreference(&ctx->obj->base);
|
drm_gem_object_unreference(&ctx->obj->base);
|
||||||
|
}
|
||||||
|
|
||||||
if (ppgtt)
|
if (ppgtt)
|
||||||
kref_put(&ppgtt->ref, ppgtt_release);
|
kref_put(&ppgtt->ref, ppgtt_release);
|
||||||
|
@ -232,32 +231,32 @@ __create_hw_context(struct drm_device *dev,
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
kref_init(&ctx->ref);
|
kref_init(&ctx->ref);
|
||||||
ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size);
|
|
||||||
INIT_LIST_HEAD(&ctx->link);
|
|
||||||
if (ctx->obj == NULL) {
|
|
||||||
kfree(ctx);
|
|
||||||
DRM_DEBUG_DRIVER("Context object allocated failed\n");
|
|
||||||
return ERR_PTR(-ENOMEM);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (INTEL_INFO(dev)->gen >= 7) {
|
|
||||||
ret = i915_gem_object_set_cache_level(ctx->obj,
|
|
||||||
I915_CACHE_L3_LLC);
|
|
||||||
/* Failure shouldn't ever happen this early */
|
|
||||||
if (WARN_ON(ret))
|
|
||||||
goto err_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
list_add_tail(&ctx->link, &dev_priv->context_list);
|
list_add_tail(&ctx->link, &dev_priv->context_list);
|
||||||
|
|
||||||
/* Default context will never have a file_priv */
|
if (dev_priv->hw_context_size) {
|
||||||
if (file_priv == NULL)
|
ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size);
|
||||||
return ctx;
|
if (ctx->obj == NULL) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
ret = idr_alloc(&file_priv->context_idr, ctx, DEFAULT_CONTEXT_ID, 0,
|
if (INTEL_INFO(dev)->gen >= 7) {
|
||||||
GFP_KERNEL);
|
ret = i915_gem_object_set_cache_level(ctx->obj,
|
||||||
if (ret < 0)
|
I915_CACHE_L3_LLC);
|
||||||
goto err_out;
|
/* Failure shouldn't ever happen this early */
|
||||||
|
if (WARN_ON(ret))
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Default context will never have a file_priv */
|
||||||
|
if (file_priv != NULL) {
|
||||||
|
ret = idr_alloc(&file_priv->context_idr, ctx,
|
||||||
|
DEFAULT_CONTEXT_ID, 0, GFP_KERNEL);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err_out;
|
||||||
|
} else
|
||||||
|
ret = DEFAULT_CONTEXT_ID;
|
||||||
|
|
||||||
ctx->file_priv = file_priv;
|
ctx->file_priv = file_priv;
|
||||||
ctx->id = ret;
|
ctx->id = ret;
|
||||||
|
@ -294,7 +293,7 @@ i915_gem_create_context(struct drm_device *dev,
|
||||||
if (IS_ERR(ctx))
|
if (IS_ERR(ctx))
|
||||||
return ctx;
|
return ctx;
|
||||||
|
|
||||||
if (is_global_default_ctx) {
|
if (is_global_default_ctx && ctx->obj) {
|
||||||
/* We may need to do things with the shrinker which
|
/* We may need to do things with the shrinker which
|
||||||
* require us to immediately switch back to the default
|
* require us to immediately switch back to the default
|
||||||
* context. This can cause a problem as pinning the
|
* context. This can cause a problem as pinning the
|
||||||
|
@ -342,7 +341,7 @@ i915_gem_create_context(struct drm_device *dev,
|
||||||
return ctx;
|
return ctx;
|
||||||
|
|
||||||
err_unpin:
|
err_unpin:
|
||||||
if (is_global_default_ctx)
|
if (is_global_default_ctx && ctx->obj)
|
||||||
i915_gem_object_ggtt_unpin(ctx->obj);
|
i915_gem_object_ggtt_unpin(ctx->obj);
|
||||||
err_destroy:
|
err_destroy:
|
||||||
i915_gem_context_unreference(ctx);
|
i915_gem_context_unreference(ctx);
|
||||||
|
@ -352,32 +351,22 @@ err_destroy:
|
||||||
void i915_gem_context_reset(struct drm_device *dev)
|
void i915_gem_context_reset(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
struct intel_ring_buffer *ring;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!HAS_HW_CONTEXTS(dev))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Prevent the hardware from restoring the last context (which hung) on
|
/* Prevent the hardware from restoring the last context (which hung) on
|
||||||
* the next switch */
|
* the next switch */
|
||||||
for (i = 0; i < I915_NUM_RINGS; i++) {
|
for (i = 0; i < I915_NUM_RINGS; i++) {
|
||||||
struct i915_hw_context *dctx;
|
struct intel_ring_buffer *ring = &dev_priv->ring[i];
|
||||||
if (!(INTEL_INFO(dev)->ring_mask & (1<<i)))
|
struct i915_hw_context *dctx = ring->default_context;
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Do a fake switch to the default context */
|
/* Do a fake switch to the default context */
|
||||||
ring = &dev_priv->ring[i];
|
if (ring->last_context == dctx)
|
||||||
dctx = ring->default_context;
|
|
||||||
if (WARN_ON(!dctx))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!ring->last_context)
|
if (!ring->last_context)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (ring->last_context == dctx)
|
if (dctx->obj && i == RCS) {
|
||||||
continue;
|
|
||||||
|
|
||||||
if (i == RCS) {
|
|
||||||
WARN_ON(i915_gem_obj_ggtt_pin(dctx->obj,
|
WARN_ON(i915_gem_obj_ggtt_pin(dctx->obj,
|
||||||
get_context_alignment(dev), 0));
|
get_context_alignment(dev), 0));
|
||||||
/* Fake a finish/inactive */
|
/* Fake a finish/inactive */
|
||||||
|
@ -394,44 +383,35 @@ void i915_gem_context_reset(struct drm_device *dev)
|
||||||
int i915_gem_context_init(struct drm_device *dev)
|
int i915_gem_context_init(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
struct intel_ring_buffer *ring;
|
struct i915_hw_context *ctx;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!HAS_HW_CONTEXTS(dev))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Init should only be called once per module load. Eventually the
|
/* Init should only be called once per module load. Eventually the
|
||||||
* restriction on the context_disabled check can be loosened. */
|
* restriction on the context_disabled check can be loosened. */
|
||||||
if (WARN_ON(dev_priv->ring[RCS].default_context))
|
if (WARN_ON(dev_priv->ring[RCS].default_context))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
dev_priv->hw_context_size = round_up(get_context_size(dev), 4096);
|
if (HAS_HW_CONTEXTS(dev)) {
|
||||||
|
dev_priv->hw_context_size = round_up(get_context_size(dev), 4096);
|
||||||
if (dev_priv->hw_context_size > (1<<20)) {
|
if (dev_priv->hw_context_size > (1<<20)) {
|
||||||
DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size\n");
|
DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size %d\n",
|
||||||
return -E2BIG;
|
dev_priv->hw_context_size);
|
||||||
|
dev_priv->hw_context_size = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_priv->ring[RCS].default_context =
|
ctx = i915_gem_create_context(dev, NULL, USES_PPGTT(dev));
|
||||||
i915_gem_create_context(dev, NULL, USES_PPGTT(dev));
|
if (IS_ERR(ctx)) {
|
||||||
|
DRM_ERROR("Failed to create default global context (error %ld)\n",
|
||||||
if (IS_ERR_OR_NULL(dev_priv->ring[RCS].default_context)) {
|
PTR_ERR(ctx));
|
||||||
DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed %ld\n",
|
return PTR_ERR(ctx);
|
||||||
PTR_ERR(dev_priv->ring[RCS].default_context));
|
|
||||||
return PTR_ERR(dev_priv->ring[RCS].default_context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = RCS + 1; i < I915_NUM_RINGS; i++) {
|
/* NB: RCS will hold a ref for all rings */
|
||||||
if (!(INTEL_INFO(dev)->ring_mask & (1<<i)))
|
for (i = 0; i < I915_NUM_RINGS; i++)
|
||||||
continue;
|
dev_priv->ring[i].default_context = ctx;
|
||||||
|
|
||||||
ring = &dev_priv->ring[i];
|
DRM_DEBUG_DRIVER("%s context support initialized\n", dev_priv->hw_context_size ? "HW" : "fake");
|
||||||
|
|
||||||
/* NB: RCS will hold a ref for all rings */
|
|
||||||
ring->default_context = dev_priv->ring[RCS].default_context;
|
|
||||||
}
|
|
||||||
|
|
||||||
DRM_DEBUG_DRIVER("HW context support initialized\n");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,33 +421,30 @@ void i915_gem_context_fini(struct drm_device *dev)
|
||||||
struct i915_hw_context *dctx = dev_priv->ring[RCS].default_context;
|
struct i915_hw_context *dctx = dev_priv->ring[RCS].default_context;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!HAS_HW_CONTEXTS(dev))
|
if (dctx->obj) {
|
||||||
return;
|
/* The only known way to stop the gpu from accessing the hw context is
|
||||||
|
* to reset it. Do this as the very last operation to avoid confusing
|
||||||
|
* other code, leading to spurious errors. */
|
||||||
|
intel_gpu_reset(dev);
|
||||||
|
|
||||||
/* The only known way to stop the gpu from accessing the hw context is
|
/* When default context is created and switched to, base object refcount
|
||||||
* to reset it. Do this as the very last operation to avoid confusing
|
* will be 2 (+1 from object creation and +1 from do_switch()).
|
||||||
* other code, leading to spurious errors. */
|
* i915_gem_context_fini() will be called after gpu_idle() has switched
|
||||||
intel_gpu_reset(dev);
|
* to default context. So we need to unreference the base object once
|
||||||
|
* to offset the do_switch part, so that i915_gem_context_unreference()
|
||||||
/* When default context is created and switched to, base object refcount
|
* can then free the base object correctly. */
|
||||||
* will be 2 (+1 from object creation and +1 from do_switch()).
|
WARN_ON(!dev_priv->ring[RCS].last_context);
|
||||||
* i915_gem_context_fini() will be called after gpu_idle() has switched
|
if (dev_priv->ring[RCS].last_context == dctx) {
|
||||||
* to default context. So we need to unreference the base object once
|
/* Fake switch to NULL context */
|
||||||
* to offset the do_switch part, so that i915_gem_context_unreference()
|
WARN_ON(dctx->obj->active);
|
||||||
* can then free the base object correctly. */
|
i915_gem_object_ggtt_unpin(dctx->obj);
|
||||||
WARN_ON(!dev_priv->ring[RCS].last_context);
|
i915_gem_context_unreference(dctx);
|
||||||
if (dev_priv->ring[RCS].last_context == dctx) {
|
dev_priv->ring[RCS].last_context = NULL;
|
||||||
/* Fake switch to NULL context */
|
}
|
||||||
WARN_ON(dctx->obj->active);
|
|
||||||
i915_gem_object_ggtt_unpin(dctx->obj);
|
|
||||||
i915_gem_context_unreference(dctx);
|
|
||||||
dev_priv->ring[RCS].last_context = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < I915_NUM_RINGS; i++) {
|
for (i = 0; i < I915_NUM_RINGS; i++) {
|
||||||
struct intel_ring_buffer *ring = &dev_priv->ring[i];
|
struct intel_ring_buffer *ring = &dev_priv->ring[i];
|
||||||
if (!(INTEL_INFO(dev)->ring_mask & (1<<i)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (ring->last_context)
|
if (ring->last_context)
|
||||||
i915_gem_context_unreference(ring->last_context);
|
i915_gem_context_unreference(ring->last_context);
|
||||||
|
@ -478,7 +455,6 @@ void i915_gem_context_fini(struct drm_device *dev)
|
||||||
|
|
||||||
i915_gem_object_ggtt_unpin(dctx->obj);
|
i915_gem_object_ggtt_unpin(dctx->obj);
|
||||||
i915_gem_context_unreference(dctx);
|
i915_gem_context_unreference(dctx);
|
||||||
dev_priv->mm.aliasing_ppgtt = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int i915_gem_context_enable(struct drm_i915_private *dev_priv)
|
int i915_gem_context_enable(struct drm_i915_private *dev_priv)
|
||||||
|
@ -486,9 +462,6 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv)
|
||||||
struct intel_ring_buffer *ring;
|
struct intel_ring_buffer *ring;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
if (!HAS_HW_CONTEXTS(dev_priv->dev))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* This is the only place the aliasing PPGTT gets enabled, which means
|
/* This is the only place the aliasing PPGTT gets enabled, which means
|
||||||
* it has to happen before we bail on reset */
|
* it has to happen before we bail on reset */
|
||||||
if (dev_priv->mm.aliasing_ppgtt) {
|
if (dev_priv->mm.aliasing_ppgtt) {
|
||||||
|
@ -503,7 +476,7 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv)
|
||||||
BUG_ON(!dev_priv->ring[RCS].default_context);
|
BUG_ON(!dev_priv->ring[RCS].default_context);
|
||||||
|
|
||||||
for_each_ring(ring, dev_priv, i) {
|
for_each_ring(ring, dev_priv, i) {
|
||||||
ret = do_switch(ring, ring->default_context);
|
ret = i915_switch_context(ring, ring->default_context);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -526,19 +499,6 @@ static int context_idr_cleanup(int id, void *p, void *data)
|
||||||
int i915_gem_context_open(struct drm_device *dev, struct drm_file *file)
|
int i915_gem_context_open(struct drm_device *dev, struct drm_file *file)
|
||||||
{
|
{
|
||||||
struct drm_i915_file_private *file_priv = file->driver_priv;
|
struct drm_i915_file_private *file_priv = file->driver_priv;
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
|
||||||
|
|
||||||
if (!HAS_HW_CONTEXTS(dev)) {
|
|
||||||
/* Cheat for hang stats */
|
|
||||||
file_priv->private_default_ctx =
|
|
||||||
kzalloc(sizeof(struct i915_hw_context), GFP_KERNEL);
|
|
||||||
|
|
||||||
if (file_priv->private_default_ctx == NULL)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
file_priv->private_default_ctx->vm = &dev_priv->gtt.base;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
idr_init(&file_priv->context_idr);
|
idr_init(&file_priv->context_idr);
|
||||||
|
|
||||||
|
@ -559,14 +519,10 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file)
|
||||||
{
|
{
|
||||||
struct drm_i915_file_private *file_priv = file->driver_priv;
|
struct drm_i915_file_private *file_priv = file->driver_priv;
|
||||||
|
|
||||||
if (!HAS_HW_CONTEXTS(dev)) {
|
|
||||||
kfree(file_priv->private_default_ctx);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL);
|
idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL);
|
||||||
i915_gem_context_unreference(file_priv->private_default_ctx);
|
|
||||||
idr_destroy(&file_priv->context_idr);
|
idr_destroy(&file_priv->context_idr);
|
||||||
|
|
||||||
|
i915_gem_context_unreference(file_priv->private_default_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct i915_hw_context *
|
struct i915_hw_context *
|
||||||
|
@ -574,9 +530,6 @@ i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id)
|
||||||
{
|
{
|
||||||
struct i915_hw_context *ctx;
|
struct i915_hw_context *ctx;
|
||||||
|
|
||||||
if (!HAS_HW_CONTEXTS(file_priv->dev_priv->dev))
|
|
||||||
return file_priv->private_default_ctx;
|
|
||||||
|
|
||||||
ctx = (struct i915_hw_context *)idr_find(&file_priv->context_idr, id);
|
ctx = (struct i915_hw_context *)idr_find(&file_priv->context_idr, id);
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return ERR_PTR(-ENOENT);
|
return ERR_PTR(-ENOENT);
|
||||||
|
@ -758,7 +711,6 @@ unpin_out:
|
||||||
/**
|
/**
|
||||||
* i915_switch_context() - perform a GPU context switch.
|
* i915_switch_context() - perform a GPU context switch.
|
||||||
* @ring: ring for which we'll execute the context switch
|
* @ring: ring for which we'll execute the context switch
|
||||||
* @file_priv: file_priv associated with the context, may be NULL
|
|
||||||
* @to: the context to switch to
|
* @to: the context to switch to
|
||||||
*
|
*
|
||||||
* The context life cycle is simple. The context refcount is incremented and
|
* The context life cycle is simple. The context refcount is incremented and
|
||||||
|
@ -767,24 +719,30 @@ unpin_out:
|
||||||
* object while letting the normal object tracking destroy the backing BO.
|
* object while letting the normal object tracking destroy the backing BO.
|
||||||
*/
|
*/
|
||||||
int i915_switch_context(struct intel_ring_buffer *ring,
|
int i915_switch_context(struct intel_ring_buffer *ring,
|
||||||
struct drm_file *file,
|
|
||||||
struct i915_hw_context *to)
|
struct i915_hw_context *to)
|
||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = ring->dev->dev_private;
|
struct drm_i915_private *dev_priv = ring->dev->dev_private;
|
||||||
|
|
||||||
WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
|
WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
|
||||||
|
|
||||||
BUG_ON(file && to == NULL);
|
if (to->obj == NULL) { /* We have the fake context */
|
||||||
|
if (to != ring->last_context) {
|
||||||
/* We have the fake context */
|
i915_gem_context_reference(to);
|
||||||
if (!HAS_HW_CONTEXTS(ring->dev)) {
|
if (ring->last_context)
|
||||||
ring->last_context = to;
|
i915_gem_context_unreference(ring->last_context);
|
||||||
|
ring->last_context = to;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return do_switch(ring, to);
|
return do_switch(ring, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool hw_context_enabled(struct drm_device *dev)
|
||||||
|
{
|
||||||
|
return to_i915(dev)->hw_context_size;
|
||||||
|
}
|
||||||
|
|
||||||
int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
|
int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
|
||||||
struct drm_file *file)
|
struct drm_file *file)
|
||||||
{
|
{
|
||||||
|
@ -793,7 +751,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
|
||||||
struct i915_hw_context *ctx;
|
struct i915_hw_context *ctx;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!HAS_HW_CONTEXTS(dev))
|
if (!hw_context_enabled(dev))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
ret = i915_mutex_lock_interruptible(dev);
|
ret = i915_mutex_lock_interruptible(dev);
|
||||||
|
|
|
@ -1221,7 +1221,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
ret = i915_switch_context(ring, file, ctx);
|
ret = i915_switch_context(ring, ctx);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
|
|
@ -287,6 +287,9 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
|
||||||
const struct bdb_lfp_backlight_data *backlight_data;
|
const struct bdb_lfp_backlight_data *backlight_data;
|
||||||
const struct bdb_lfp_backlight_data_entry *entry;
|
const struct bdb_lfp_backlight_data_entry *entry;
|
||||||
|
|
||||||
|
/* Err to enabling backlight if no backlight block. */
|
||||||
|
dev_priv->vbt.backlight.present = true;
|
||||||
|
|
||||||
backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT);
|
backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT);
|
||||||
if (!backlight_data)
|
if (!backlight_data)
|
||||||
return;
|
return;
|
||||||
|
@ -299,6 +302,13 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
|
||||||
|
|
||||||
entry = &backlight_data->data[panel_type];
|
entry = &backlight_data->data[panel_type];
|
||||||
|
|
||||||
|
dev_priv->vbt.backlight.present = entry->type == BDB_BACKLIGHT_TYPE_PWM;
|
||||||
|
if (!dev_priv->vbt.backlight.present) {
|
||||||
|
DRM_DEBUG_KMS("PWM backlight not present in VBT (type %u)\n",
|
||||||
|
entry->type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
|
dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
|
||||||
dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm;
|
dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm;
|
||||||
DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, "
|
DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, "
|
||||||
|
|
|
@ -374,6 +374,9 @@ struct bdb_lvds_lfp_data {
|
||||||
struct bdb_lvds_lfp_data_entry data[16];
|
struct bdb_lvds_lfp_data_entry data[16];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
#define BDB_BACKLIGHT_TYPE_NONE 0
|
||||||
|
#define BDB_BACKLIGHT_TYPE_PWM 2
|
||||||
|
|
||||||
struct bdb_lfp_backlight_data_entry {
|
struct bdb_lfp_backlight_data_entry {
|
||||||
u8 type:2;
|
u8 type:2;
|
||||||
u8 active_low_pwm:1;
|
u8 active_low_pwm:1;
|
||||||
|
|
|
@ -1065,6 +1065,11 @@ int intel_panel_setup_backlight(struct drm_connector *connector)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (!dev_priv->vbt.backlight.present) {
|
||||||
|
DRM_DEBUG_KMS("native backlight control not available per VBT\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* set level and max in panel struct */
|
/* set level and max in panel struct */
|
||||||
spin_lock_irqsave(&dev_priv->backlight_lock, flags);
|
spin_lock_irqsave(&dev_priv->backlight_lock, flags);
|
||||||
ret = dev_priv->display.setup_backlight(intel_connector);
|
ret = dev_priv->display.setup_backlight(intel_connector);
|
||||||
|
|
|
@ -1545,6 +1545,16 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc)
|
||||||
|
|
||||||
DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm);
|
DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm);
|
||||||
|
|
||||||
|
if (IS_I915GM(dev) && enabled) {
|
||||||
|
struct intel_framebuffer *fb;
|
||||||
|
|
||||||
|
fb = to_intel_framebuffer(enabled->primary->fb);
|
||||||
|
|
||||||
|
/* self-refresh seems busted with untiled */
|
||||||
|
if (fb->obj->tiling_mode == I915_TILING_NONE)
|
||||||
|
enabled = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Overlay gets an aggressive default since video jitter is bad.
|
* Overlay gets an aggressive default since video jitter is bad.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue