diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_context.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_sysfs.c | 37 |
4 files changed, 41 insertions, 27 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index ada095023dad..80bed69fe5b7 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
@@ -145,6 +145,13 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) | |||
145 | seq_printf(m, " (%s)", obj->ring->name); | 145 | seq_printf(m, " (%s)", obj->ring->name); |
146 | } | 146 | } |
147 | 147 | ||
148 | static void describe_ctx(struct seq_file *m, struct i915_hw_context *ctx) | ||
149 | { | ||
150 | seq_putc(m, ctx->is_initialized ? 'I' : 'i'); | ||
151 | seq_putc(m, ctx->remap_slice ? 'R' : 'r'); | ||
152 | seq_putc(m, ' '); | ||
153 | } | ||
154 | |||
148 | static int i915_gem_object_list_info(struct seq_file *m, void *data) | 155 | static int i915_gem_object_list_info(struct seq_file *m, void *data) |
149 | { | 156 | { |
150 | struct drm_info_node *node = (struct drm_info_node *) m->private; | 157 | struct drm_info_node *node = (struct drm_info_node *) m->private; |
@@ -1463,6 +1470,7 @@ static int i915_context_status(struct seq_file *m, void *unused) | |||
1463 | 1470 | ||
1464 | list_for_each_entry(ctx, &dev_priv->context_list, link) { | 1471 | list_for_each_entry(ctx, &dev_priv->context_list, link) { |
1465 | seq_puts(m, "HW context "); | 1472 | seq_puts(m, "HW context "); |
1473 | describe_ctx(m, ctx); | ||
1466 | for_each_ring(ring, dev_priv, i) | 1474 | for_each_ring(ring, dev_priv, i) |
1467 | if (ring->default_context == ctx) | 1475 | if (ring->default_context == ctx) |
1468 | seq_printf(m, "(default context %s) ", ring->name); | 1476 | seq_printf(m, "(default context %s) ", ring->name); |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 179592762537..015df5264dcc 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -601,6 +601,7 @@ struct i915_hw_context { | |||
601 | struct kref ref; | 601 | struct kref ref; |
602 | int id; | 602 | int id; |
603 | bool is_initialized; | 603 | bool is_initialized; |
604 | uint8_t remap_slice; | ||
604 | struct drm_i915_file_private *file_priv; | 605 | struct drm_i915_file_private *file_priv; |
605 | struct intel_ring_buffer *ring; | 606 | struct intel_ring_buffer *ring; |
606 | struct drm_i915_gem_object *obj; | 607 | struct drm_i915_gem_object *obj; |
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 2bbdce821ac3..9af3fe7e42b0 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c | |||
@@ -181,6 +181,10 @@ create_hw_context(struct drm_device *dev, | |||
181 | 181 | ||
182 | ctx->file_priv = file_priv; | 182 | ctx->file_priv = file_priv; |
183 | ctx->id = ret; | 183 | ctx->id = ret; |
184 | /* NB: Mark all slices as needing a remap so that when the context first | ||
185 | * loads it will restore whatever remap state already exists. If there | ||
186 | * is no remap info, it will be a NOP. */ | ||
187 | ctx->remap_slice = (1 << NUM_L3_SLICES(dev)) - 1; | ||
184 | 188 | ||
185 | return ctx; | 189 | return ctx; |
186 | 190 | ||
@@ -396,11 +400,11 @@ static int do_switch(struct i915_hw_context *to) | |||
396 | struct intel_ring_buffer *ring = to->ring; | 400 | struct intel_ring_buffer *ring = to->ring; |
397 | struct i915_hw_context *from = ring->last_context; | 401 | struct i915_hw_context *from = ring->last_context; |
398 | u32 hw_flags = 0; | 402 | u32 hw_flags = 0; |
399 | int ret; | 403 | int ret, i; |
400 | 404 | ||
401 | BUG_ON(from != NULL && from->obj != NULL && from->obj->pin_count == 0); | 405 | BUG_ON(from != NULL && from->obj != NULL && from->obj->pin_count == 0); |
402 | 406 | ||
403 | if (from == to) | 407 | if (from == to && !to->remap_slice) |
404 | return 0; | 408 | return 0; |
405 | 409 | ||
406 | ret = i915_gem_obj_ggtt_pin(to->obj, CONTEXT_ALIGN, false, false); | 410 | ret = i915_gem_obj_ggtt_pin(to->obj, CONTEXT_ALIGN, false, false); |
@@ -423,8 +427,6 @@ static int do_switch(struct i915_hw_context *to) | |||
423 | 427 | ||
424 | if (!to->is_initialized || is_default_context(to)) | 428 | if (!to->is_initialized || is_default_context(to)) |
425 | hw_flags |= MI_RESTORE_INHIBIT; | 429 | hw_flags |= MI_RESTORE_INHIBIT; |
426 | else if (WARN_ON_ONCE(from == to)) /* not yet expected */ | ||
427 | hw_flags |= MI_FORCE_RESTORE; | ||
428 | 430 | ||
429 | ret = mi_set_context(ring, to, hw_flags); | 431 | ret = mi_set_context(ring, to, hw_flags); |
430 | if (ret) { | 432 | if (ret) { |
@@ -432,6 +434,18 @@ static int do_switch(struct i915_hw_context *to) | |||
432 | return ret; | 434 | return ret; |
433 | } | 435 | } |
434 | 436 | ||
437 | for (i = 0; i < MAX_L3_SLICES; i++) { | ||
438 | if (!(to->remap_slice & (1<<i))) | ||
439 | continue; | ||
440 | |||
441 | ret = i915_gem_l3_remap(ring, i); | ||
442 | /* If it failed, try again next round */ | ||
443 | if (ret) | ||
444 | DRM_DEBUG_DRIVER("L3 remapping failed\n"); | ||
445 | else | ||
446 | to->remap_slice &= ~(1<<i); | ||
447 | } | ||
448 | |||
435 | /* The backing object for the context is done after switching to the | 449 | /* The backing object for the context is done after switching to the |
436 | * *next* context. Therefore we cannot retire the previous context until | 450 | * *next* context. Therefore we cannot retire the previous context until |
437 | * the next context has already started running. In fact, the below code | 451 | * the next context has already started running. In fact, the below code |
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index b07bdfb8892d..deb8787308d6 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c | |||
@@ -118,9 +118,8 @@ i915_l3_read(struct file *filp, struct kobject *kobj, | |||
118 | struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev); | 118 | struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev); |
119 | struct drm_device *drm_dev = dminor->dev; | 119 | struct drm_device *drm_dev = dminor->dev; |
120 | struct drm_i915_private *dev_priv = drm_dev->dev_private; | 120 | struct drm_i915_private *dev_priv = drm_dev->dev_private; |
121 | uint32_t misccpctl; | ||
122 | int slice = (int)(uintptr_t)attr->private; | 121 | int slice = (int)(uintptr_t)attr->private; |
123 | int i, ret; | 122 | int ret; |
124 | 123 | ||
125 | count = round_down(count, 4); | 124 | count = round_down(count, 4); |
126 | 125 | ||
@@ -134,26 +133,13 @@ i915_l3_read(struct file *filp, struct kobject *kobj, | |||
134 | if (ret) | 133 | if (ret) |
135 | return ret; | 134 | return ret; |
136 | 135 | ||
137 | if (IS_HASWELL(drm_dev)) { | 136 | if (dev_priv->l3_parity.remap_info[slice]) |
138 | if (dev_priv->l3_parity.remap_info[slice]) | 137 | memcpy(buf, |
139 | memcpy(buf, | 138 | dev_priv->l3_parity.remap_info[slice] + (offset/4), |
140 | dev_priv->l3_parity.remap_info[slice] + (offset/4), | 139 | count); |
141 | count); | 140 | else |
142 | else | 141 | memset(buf, 0, count); |
143 | memset(buf, 0, count); | ||
144 | |||
145 | goto out; | ||
146 | } | ||
147 | |||
148 | misccpctl = I915_READ(GEN7_MISCCPCTL); | ||
149 | I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); | ||
150 | |||
151 | for (i = 0; i < count; i += 4) | ||
152 | *((uint32_t *)(&buf[i])) = I915_READ(GEN7_L3LOG_BASE + offset + i); | ||
153 | |||
154 | I915_WRITE(GEN7_MISCCPCTL, misccpctl); | ||
155 | 142 | ||
156 | out: | ||
157 | mutex_unlock(&drm_dev->struct_mutex); | 143 | mutex_unlock(&drm_dev->struct_mutex); |
158 | 144 | ||
159 | return count; | 145 | return count; |
@@ -168,6 +154,7 @@ i915_l3_write(struct file *filp, struct kobject *kobj, | |||
168 | struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev); | 154 | struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev); |
169 | struct drm_device *drm_dev = dminor->dev; | 155 | struct drm_device *drm_dev = dminor->dev; |
170 | struct drm_i915_private *dev_priv = drm_dev->dev_private; | 156 | struct drm_i915_private *dev_priv = drm_dev->dev_private; |
157 | struct i915_hw_context *ctx; | ||
171 | u32 *temp = NULL; /* Just here to make handling failures easy */ | 158 | u32 *temp = NULL; /* Just here to make handling failures easy */ |
172 | int slice = (int)(uintptr_t)attr->private; | 159 | int slice = (int)(uintptr_t)attr->private; |
173 | int ret; | 160 | int ret; |
@@ -176,6 +163,9 @@ i915_l3_write(struct file *filp, struct kobject *kobj, | |||
176 | if (ret) | 163 | if (ret) |
177 | return ret; | 164 | return ret; |
178 | 165 | ||
166 | if (dev_priv->hw_contexts_disabled) | ||
167 | return -ENXIO; | ||
168 | |||
179 | ret = i915_mutex_lock_interruptible(drm_dev); | 169 | ret = i915_mutex_lock_interruptible(drm_dev); |
180 | if (ret) | 170 | if (ret) |
181 | return ret; | 171 | return ret; |
@@ -204,8 +194,9 @@ i915_l3_write(struct file *filp, struct kobject *kobj, | |||
204 | 194 | ||
205 | memcpy(dev_priv->l3_parity.remap_info[slice] + (offset/4), buf, count); | 195 | memcpy(dev_priv->l3_parity.remap_info[slice] + (offset/4), buf, count); |
206 | 196 | ||
207 | if (i915_gem_l3_remap(&dev_priv->ring[RCS], slice)) | 197 | /* NB: We defer the remapping until we switch to the context */ |
208 | count = 0; | 198 | list_for_each_entry(ctx, &dev_priv->context_list, link) |
199 | ctx->remap_slice |= (1<<slice); | ||
209 | 200 | ||
210 | mutex_unlock(&drm_dev->struct_mutex); | 201 | mutex_unlock(&drm_dev->struct_mutex); |
211 | 202 | ||