Skip to content

Commit 8be0e5c

Browse files
committed
Merge branch 'drm-intel-fixes' of git://people.freedesktop.org/~danvet/drm-intel into drm-next
Some fixes for 3.8: - Watermark fixups from Chris Wilson (4 pieces). - 2 snb workarounds, seem to be recently added to our internal DB. - workaround for the infamous i830/i845 hang, seems now finally solid! Based on Chris' fix for SNA, now also for UXA/mesa&old SNA. - Some more fixlets for shrinker-pulls-the-rug issues (Chris&me). - Fix dma-buf flags when exporting (you). - Disable the VGA plane if it's enabled on lid open - similar fix in spirit to the one I've sent you last weeek, BIOS' really like to mess with the display when closing the lid (awesome debug work from Krzysztof Mazur). * 'drm-intel-fixes' of git://people.freedesktop.org/~danvet/drm-intel: drm/i915: disable shrinker lock stealing for create_mmap_offset drm/i915: optionally disable shrinker lock stealing drm/i915: fix flags in dma buf exporting i915: ensure that VGA plane is disabled drm/i915: Preallocate the drm_mm_node prior to manipulating the GTT drm_mm manager drm: Export routines for inserting preallocated nodes into the mm manager drm/i915: don't disable disconnected outputs drm/i915: Implement workaround for broken CS tlb on i830/845 drm/i915: Implement WaSetupGtModeTdRowDispatch drm/i915: Implement WaDisableHiZPlanesWhenMSAAEnabled drm/i915: Prefer CRTC 'active' rather than 'enabled' during WM computations drm/i915: Clear self-refresh watermarks when disabled drm/i915: Double the cursor self-refresh latency on Valleyview drm/i915: Fixup cursor latency used for IVB lp3 watermarks
2 parents b1d778b + da494d7 commit 8be0e5c

File tree

14 files changed

+356
-88
lines changed

14 files changed

+356
-88
lines changed

drivers/gpu/drm/drm_mm.c

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -184,19 +184,27 @@ EXPORT_SYMBOL(drm_mm_get_block_generic);
184184
* -ENOSPC if no suitable free area is available. The preallocated memory node
185185
* must be cleared.
186186
*/
187-
int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node,
188-
unsigned long size, unsigned alignment)
187+
int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node,
188+
unsigned long size, unsigned alignment,
189+
unsigned long color)
189190
{
190191
struct drm_mm_node *hole_node;
191192

192-
hole_node = drm_mm_search_free(mm, size, alignment, false);
193+
hole_node = drm_mm_search_free_generic(mm, size, alignment,
194+
color, 0);
193195
if (!hole_node)
194196
return -ENOSPC;
195197

196-
drm_mm_insert_helper(hole_node, node, size, alignment, 0);
197-
198+
drm_mm_insert_helper(hole_node, node, size, alignment, color);
198199
return 0;
199200
}
201+
EXPORT_SYMBOL(drm_mm_insert_node_generic);
202+
203+
int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node,
204+
unsigned long size, unsigned alignment)
205+
{
206+
return drm_mm_insert_node_generic(mm, node, size, alignment, 0);
207+
}
200208
EXPORT_SYMBOL(drm_mm_insert_node);
201209

202210
static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
@@ -275,22 +283,31 @@ EXPORT_SYMBOL(drm_mm_get_block_range_generic);
275283
* -ENOSPC if no suitable free area is available. This is for range
276284
* restricted allocations. The preallocated memory node must be cleared.
277285
*/
278-
int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node,
279-
unsigned long size, unsigned alignment,
280-
unsigned long start, unsigned long end)
286+
int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct drm_mm_node *node,
287+
unsigned long size, unsigned alignment, unsigned long color,
288+
unsigned long start, unsigned long end)
281289
{
282290
struct drm_mm_node *hole_node;
283291

284-
hole_node = drm_mm_search_free_in_range(mm, size, alignment,
285-
start, end, false);
292+
hole_node = drm_mm_search_free_in_range_generic(mm,
293+
size, alignment, color,
294+
start, end, 0);
286295
if (!hole_node)
287296
return -ENOSPC;
288297

289-
drm_mm_insert_helper_range(hole_node, node, size, alignment, 0,
298+
drm_mm_insert_helper_range(hole_node, node,
299+
size, alignment, color,
290300
start, end);
291-
292301
return 0;
293302
}
303+
EXPORT_SYMBOL(drm_mm_insert_node_in_range_generic);
304+
305+
int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node,
306+
unsigned long size, unsigned alignment,
307+
unsigned long start, unsigned long end)
308+
{
309+
return drm_mm_insert_node_in_range_generic(mm, node, size, alignment, 0, start, end);
310+
}
294311
EXPORT_SYMBOL(drm_mm_insert_node_in_range);
295312

296313
/**

drivers/gpu/drm/i915/i915_dma.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
989989
case I915_PARAM_HAS_SECURE_BATCHES:
990990
value = capable(CAP_SYS_ADMIN);
991991
break;
992+
case I915_PARAM_HAS_PINNED_BATCHES:
993+
value = 1;
994+
break;
992995
default:
993996
DRM_DEBUG_DRIVER("Unknown parameter %d\n",
994997
param->param);

drivers/gpu/drm/i915/i915_drv.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,7 @@ typedef struct drm_i915_private {
780780
struct i915_hw_ppgtt *aliasing_ppgtt;
781781

782782
struct shrinker inactive_shrinker;
783+
bool shrinker_no_lock_stealing;
783784

784785
/**
785786
* List of objects currently involved in rendering.
@@ -1100,6 +1101,7 @@ struct drm_i915_gem_object {
11001101
*/
11011102
atomic_t pending_flip;
11021103
};
1104+
#define to_gem_object(obj) (&((struct drm_i915_gem_object *)(obj))->base)
11031105

11041106
#define to_intel_bo(x) container_of(x, struct drm_i915_gem_object, base)
11051107

@@ -1166,6 +1168,9 @@ struct drm_i915_file_private {
11661168
#define IS_IVB_GT1(dev) ((dev)->pci_device == 0x0156 || \
11671169
(dev)->pci_device == 0x0152 || \
11681170
(dev)->pci_device == 0x015a)
1171+
#define IS_SNB_GT1(dev) ((dev)->pci_device == 0x0102 || \
1172+
(dev)->pci_device == 0x0106 || \
1173+
(dev)->pci_device == 0x010A)
11691174
#define IS_VALLEYVIEW(dev) (INTEL_INFO(dev)->is_valleyview)
11701175
#define IS_HASWELL(dev) (INTEL_INFO(dev)->is_haswell)
11711176
#define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile)
@@ -1196,6 +1201,9 @@ struct drm_i915_file_private {
11961201
#define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay)
11971202
#define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical)
11981203

1204+
/* Early gen2 have a totally busted CS tlb and require pinned batches. */
1205+
#define HAS_BROKEN_CS_TLB(dev) (IS_I830(dev) || IS_845G(dev))
1206+
11991207
/* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
12001208
* rows, which changed the alignment requirements and fence programming.
12011209
*/

drivers/gpu/drm/i915/i915_gem.c

Lines changed: 37 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1517,9 +1517,11 @@ static int i915_gem_object_create_mmap_offset(struct drm_i915_gem_object *obj)
15171517
if (obj->base.map_list.map)
15181518
return 0;
15191519

1520+
dev_priv->mm.shrinker_no_lock_stealing = true;
1521+
15201522
ret = drm_gem_create_mmap_offset(&obj->base);
15211523
if (ret != -ENOSPC)
1522-
return ret;
1524+
goto out;
15231525

15241526
/* Badly fragmented mmap space? The only way we can recover
15251527
* space is by destroying unwanted objects. We can't randomly release
@@ -1531,10 +1533,14 @@ static int i915_gem_object_create_mmap_offset(struct drm_i915_gem_object *obj)
15311533
i915_gem_purge(dev_priv, obj->base.size >> PAGE_SHIFT);
15321534
ret = drm_gem_create_mmap_offset(&obj->base);
15331535
if (ret != -ENOSPC)
1534-
return ret;
1536+
goto out;
15351537

15361538
i915_gem_shrink_all(dev_priv);
1537-
return drm_gem_create_mmap_offset(&obj->base);
1539+
ret = drm_gem_create_mmap_offset(&obj->base);
1540+
out:
1541+
dev_priv->mm.shrinker_no_lock_stealing = false;
1542+
1543+
return ret;
15381544
}
15391545

15401546
static void i915_gem_object_free_mmap_offset(struct drm_i915_gem_object *obj)
@@ -2890,7 +2896,7 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
28902896
{
28912897
struct drm_device *dev = obj->base.dev;
28922898
drm_i915_private_t *dev_priv = dev->dev_private;
2893-
struct drm_mm_node *free_space;
2899+
struct drm_mm_node *node;
28942900
u32 size, fence_size, fence_alignment, unfenced_alignment;
28952901
bool mappable, fenceable;
28962902
int ret;
@@ -2936,66 +2942,54 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
29362942

29372943
i915_gem_object_pin_pages(obj);
29382944

2945+
node = kzalloc(sizeof(*node), GFP_KERNEL);
2946+
if (node == NULL) {
2947+
i915_gem_object_unpin_pages(obj);
2948+
return -ENOMEM;
2949+
}
2950+
29392951
search_free:
29402952
if (map_and_fenceable)
2941-
free_space = drm_mm_search_free_in_range_color(&dev_priv->mm.gtt_space,
2942-
size, alignment, obj->cache_level,
2943-
0, dev_priv->mm.gtt_mappable_end,
2944-
false);
2953+
ret = drm_mm_insert_node_in_range_generic(&dev_priv->mm.gtt_space, node,
2954+
size, alignment, obj->cache_level,
2955+
0, dev_priv->mm.gtt_mappable_end);
29452956
else
2946-
free_space = drm_mm_search_free_color(&dev_priv->mm.gtt_space,
2947-
size, alignment, obj->cache_level,
2948-
false);
2949-
2950-
if (free_space != NULL) {
2951-
if (map_and_fenceable)
2952-
free_space =
2953-
drm_mm_get_block_range_generic(free_space,
2954-
size, alignment, obj->cache_level,
2955-
0, dev_priv->mm.gtt_mappable_end,
2956-
false);
2957-
else
2958-
free_space =
2959-
drm_mm_get_block_generic(free_space,
2960-
size, alignment, obj->cache_level,
2961-
false);
2962-
}
2963-
if (free_space == NULL) {
2957+
ret = drm_mm_insert_node_generic(&dev_priv->mm.gtt_space, node,
2958+
size, alignment, obj->cache_level);
2959+
if (ret) {
29642960
ret = i915_gem_evict_something(dev, size, alignment,
29652961
obj->cache_level,
29662962
map_and_fenceable,
29672963
nonblocking);
2968-
if (ret) {
2969-
i915_gem_object_unpin_pages(obj);
2970-
return ret;
2971-
}
2964+
if (ret == 0)
2965+
goto search_free;
29722966

2973-
goto search_free;
2967+
i915_gem_object_unpin_pages(obj);
2968+
kfree(node);
2969+
return ret;
29742970
}
2975-
if (WARN_ON(!i915_gem_valid_gtt_space(dev,
2976-
free_space,
2977-
obj->cache_level))) {
2971+
if (WARN_ON(!i915_gem_valid_gtt_space(dev, node, obj->cache_level))) {
29782972
i915_gem_object_unpin_pages(obj);
2979-
drm_mm_put_block(free_space);
2973+
drm_mm_put_block(node);
29802974
return -EINVAL;
29812975
}
29822976

29832977
ret = i915_gem_gtt_prepare_object(obj);
29842978
if (ret) {
29852979
i915_gem_object_unpin_pages(obj);
2986-
drm_mm_put_block(free_space);
2980+
drm_mm_put_block(node);
29872981
return ret;
29882982
}
29892983

29902984
list_move_tail(&obj->gtt_list, &dev_priv->mm.bound_list);
29912985
list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
29922986

2993-
obj->gtt_space = free_space;
2994-
obj->gtt_offset = free_space->start;
2987+
obj->gtt_space = node;
2988+
obj->gtt_offset = node->start;
29952989

29962990
fenceable =
2997-
free_space->size == fence_size &&
2998-
(free_space->start & (fence_alignment - 1)) == 0;
2991+
node->size == fence_size &&
2992+
(node->start & (fence_alignment - 1)) == 0;
29992993

30002994
mappable =
30012995
obj->gtt_offset + obj->base.size <= dev_priv->mm.gtt_mappable_end;
@@ -4392,6 +4386,9 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc)
43924386
if (!mutex_is_locked_by(&dev->struct_mutex, current))
43934387
return 0;
43944388

4389+
if (dev_priv->mm.shrinker_no_lock_stealing)
4390+
return 0;
4391+
43954392
unlock = false;
43964393
}
43974394

drivers/gpu/drm/i915/i915_gem_dmabuf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
226226
{
227227
struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
228228

229-
return dma_buf_export(obj, &i915_dmabuf_ops, obj->base.size, 0600);
229+
return dma_buf_export(obj, &i915_dmabuf_ops, obj->base.size, flags);
230230
}
231231

232232
static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)

drivers/gpu/drm/i915/i915_gem_execbuffer.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
808808

809809
flags |= I915_DISPATCH_SECURE;
810810
}
811+
if (args->flags & I915_EXEC_IS_PINNED)
812+
flags |= I915_DISPATCH_PINNED;
811813

812814
switch (args->flags & I915_EXEC_RING_MASK) {
813815
case I915_EXEC_DEFAULT:

drivers/gpu/drm/i915/i915_irq.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,6 +1087,18 @@ i915_error_first_batchbuffer(struct drm_i915_private *dev_priv,
10871087
if (!ring->get_seqno)
10881088
return NULL;
10891089

1090+
if (HAS_BROKEN_CS_TLB(dev_priv->dev)) {
1091+
u32 acthd = I915_READ(ACTHD);
1092+
1093+
if (WARN_ON(ring->id != RCS))
1094+
return NULL;
1095+
1096+
obj = ring->private;
1097+
if (acthd >= obj->gtt_offset &&
1098+
acthd < obj->gtt_offset + obj->base.size)
1099+
return i915_error_object_create(dev_priv, obj);
1100+
}
1101+
10901102
seqno = ring->get_seqno(ring, false);
10911103
list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) {
10921104
if (obj->ring != ring)

drivers/gpu/drm/i915/i915_reg.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,7 @@
517517
* the enables for writing to the corresponding low bit.
518518
*/
519519
#define _3D_CHICKEN 0x02084
520+
#define _3D_CHICKEN_HIZ_PLANE_DISABLE_MSAA_4X_SNB (1 << 10)
520521
#define _3D_CHICKEN2 0x0208c
521522
/* Disables pipelining of read flushes past the SF-WIZ interface.
522523
* Required on all Ironlake steppings according to the B-Spec, but the
@@ -532,7 +533,8 @@
532533
# define MI_FLUSH_ENABLE (1 << 12)
533534

534535
#define GEN6_GT_MODE 0x20d0
535-
#define GEN6_GT_MODE_HI (1 << 9)
536+
#define GEN6_GT_MODE_HI (1 << 9)
537+
#define GEN6_TD_FOUR_ROW_DISPATCH_DISABLE (1 << 5)
536538

537539
#define GFX_MODE 0x02520
538540
#define GFX_MODE_GEN7 0x0229c

drivers/gpu/drm/i915/intel_display.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8144,10 +8144,6 @@ intel_modeset_stage_output_state(struct drm_device *dev,
81448144
DRM_DEBUG_KMS("encoder changed, full mode switch\n");
81458145
config->mode_changed = true;
81468146
}
8147-
8148-
/* Disable all disconnected encoders. */
8149-
if (connector->base.status == connector_status_disconnected)
8150-
connector->new_encoder = NULL;
81518147
}
81528148
/* connector->new_encoder is now updated for all connectors. */
81538149

@@ -9167,6 +9163,23 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
91679163
* the crtc fixup. */
91689164
}
91699165

9166+
static void i915_redisable_vga(struct drm_device *dev)
9167+
{
9168+
struct drm_i915_private *dev_priv = dev->dev_private;
9169+
u32 vga_reg;
9170+
9171+
if (HAS_PCH_SPLIT(dev))
9172+
vga_reg = CPU_VGACNTRL;
9173+
else
9174+
vga_reg = VGACNTRL;
9175+
9176+
if (I915_READ(vga_reg) != VGA_DISP_DISABLE) {
9177+
DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
9178+
I915_WRITE(vga_reg, VGA_DISP_DISABLE);
9179+
POSTING_READ(vga_reg);
9180+
}
9181+
}
9182+
91709183
/* Scan out the current hw modeset state, sanitizes it and maps it into the drm
91719184
* and i915 state tracking structures. */
91729185
void intel_modeset_setup_hw_state(struct drm_device *dev,
@@ -9275,6 +9288,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
92759288
intel_set_mode(&crtc->base, &crtc->base.mode,
92769289
crtc->base.x, crtc->base.y, crtc->base.fb);
92779290
}
9291+
9292+
i915_redisable_vga(dev);
92789293
} else {
92799294
intel_modeset_update_staged_output_state(dev);
92809295
}

0 commit comments

Comments
 (0)