Skip to content

Commit 51658c0

Browse files
committed
Merge tag 'drm-intel-fixes-2019-11-21' of git://anongit.freedesktop.org/drm/drm-intel into drm-fixes
- Fix kernel oops on dumb_create ioctl on no crtc situation - Fix bad ugly colored flash on VLV/CHV related to gamma LUT update - Fix unity of the frequencies reported on PMU - Fix kernel oops on set_page_dirty using better locks around it - Protect the request pointer with RCU to prevent it being freed while we might need still - Make pool objects read-only - Restore physical addresses for fb_map to avoid corrupted page table Signed-off-by: Dave Airlie <[email protected]> From: Rodrigo Vivi <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
2 parents f824c1b + 71d1226 commit 51658c0

File tree

9 files changed

+141
-18
lines changed

9 files changed

+141
-18
lines changed

drivers/gpu/drm/i915/display/intel_atomic.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
201201
crtc_state->update_wm_post = false;
202202
crtc_state->fb_changed = false;
203203
crtc_state->fifo_changed = false;
204+
crtc_state->preload_luts = false;
204205
crtc_state->wm.need_postvbl_update = false;
205206
crtc_state->fb_bits = 0;
206207
crtc_state->update_planes = 0;

drivers/gpu/drm/i915/display/intel_color.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,55 @@ void intel_color_commit(const struct intel_crtc_state *crtc_state)
990990
dev_priv->display.color_commit(crtc_state);
991991
}
992992

993+
static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
994+
{
995+
struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
996+
struct intel_atomic_state *state =
997+
to_intel_atomic_state(new_crtc_state->base.state);
998+
const struct intel_crtc_state *old_crtc_state =
999+
intel_atomic_get_old_crtc_state(state, crtc);
1000+
1001+
return !old_crtc_state->base.gamma_lut &&
1002+
!old_crtc_state->base.degamma_lut;
1003+
}
1004+
1005+
static bool chv_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
1006+
{
1007+
struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
1008+
struct intel_atomic_state *state =
1009+
to_intel_atomic_state(new_crtc_state->base.state);
1010+
const struct intel_crtc_state *old_crtc_state =
1011+
intel_atomic_get_old_crtc_state(state, crtc);
1012+
1013+
/*
1014+
* CGM_PIPE_MODE is itself single buffered. We'd have to
1015+
* somehow split it out from chv_load_luts() if we wanted
1016+
* the ability to preload the CGM LUTs/CSC without tearing.
1017+
*/
1018+
if (old_crtc_state->cgm_mode || new_crtc_state->cgm_mode)
1019+
return false;
1020+
1021+
return !old_crtc_state->base.gamma_lut;
1022+
}
1023+
1024+
static bool glk_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
1025+
{
1026+
struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
1027+
struct intel_atomic_state *state =
1028+
to_intel_atomic_state(new_crtc_state->base.state);
1029+
const struct intel_crtc_state *old_crtc_state =
1030+
intel_atomic_get_old_crtc_state(state, crtc);
1031+
1032+
/*
1033+
* The hardware degamma is active whenever the pipe
1034+
* CSC is active. Thus even if the old state has no
1035+
* software degamma we need to avoid clobbering the
1036+
* linear hardware degamma mid scanout.
1037+
*/
1038+
return !old_crtc_state->csc_enable &&
1039+
!old_crtc_state->base.gamma_lut;
1040+
}
1041+
9931042
int intel_color_check(struct intel_crtc_state *crtc_state)
9941043
{
9951044
struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
@@ -1133,6 +1182,8 @@ static int i9xx_color_check(struct intel_crtc_state *crtc_state)
11331182
if (ret)
11341183
return ret;
11351184

1185+
crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
1186+
11361187
return 0;
11371188
}
11381189

@@ -1185,6 +1236,8 @@ static int chv_color_check(struct intel_crtc_state *crtc_state)
11851236
if (ret)
11861237
return ret;
11871238

1239+
crtc_state->preload_luts = chv_can_preload_luts(crtc_state);
1240+
11881241
return 0;
11891242
}
11901243

@@ -1224,6 +1277,8 @@ static int ilk_color_check(struct intel_crtc_state *crtc_state)
12241277
if (ret)
12251278
return ret;
12261279

1280+
crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
1281+
12271282
return 0;
12281283
}
12291284

@@ -1281,6 +1336,8 @@ static int ivb_color_check(struct intel_crtc_state *crtc_state)
12811336
if (ret)
12821337
return ret;
12831338

1339+
crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
1340+
12841341
return 0;
12851342
}
12861343

@@ -1319,6 +1376,8 @@ static int glk_color_check(struct intel_crtc_state *crtc_state)
13191376
if (ret)
13201377
return ret;
13211378

1379+
crtc_state->preload_luts = glk_can_preload_luts(crtc_state);
1380+
13221381
return 0;
13231382
}
13241383

@@ -1368,6 +1427,8 @@ static int icl_color_check(struct intel_crtc_state *crtc_state)
13681427

13691428
crtc_state->csc_mode = icl_csc_mode(crtc_state);
13701429

1430+
crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
1431+
13711432
return 0;
13721433
}
13731434

drivers/gpu/drm/i915/display/intel_display.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2504,6 +2504,9 @@ u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
25042504
* the highest stride limits of them all.
25052505
*/
25062506
crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_A);
2507+
if (!crtc)
2508+
return 0;
2509+
25072510
plane = to_intel_plane(crtc->base.primary);
25082511

25092512
return plane->max_stride(plane, pixel_format, modifier,
@@ -13740,6 +13743,11 @@ static void intel_update_crtc(struct intel_crtc *crtc,
1374013743
/* vblanks work again, re-enable pipe CRC. */
1374113744
intel_crtc_enable_pipe_crc(crtc);
1374213745
} else {
13746+
if (new_crtc_state->preload_luts &&
13747+
(new_crtc_state->base.color_mgmt_changed ||
13748+
new_crtc_state->update_pipe))
13749+
intel_color_load_luts(new_crtc_state);
13750+
1374313751
intel_pre_plane_update(old_crtc_state, new_crtc_state);
1374413752

1374513753
if (new_crtc_state->update_pipe)
@@ -14034,6 +14042,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
1403414042
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
1403514043
if (new_crtc_state->base.active &&
1403614044
!needs_modeset(new_crtc_state) &&
14045+
!new_crtc_state->preload_luts &&
1403714046
(new_crtc_state->base.color_mgmt_changed ||
1403814047
new_crtc_state->update_pipe))
1403914048
intel_color_load_luts(new_crtc_state);

drivers/gpu/drm/i915/display/intel_display_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,7 @@ struct intel_crtc_state {
761761
bool update_wm_pre, update_wm_post; /* watermarks are updated */
762762
bool fb_changed; /* fb on any of the planes is changed */
763763
bool fifo_changed; /* FIFO split is changed */
764+
bool preload_luts;
764765

765766
/* Pipe source size (ie. panel fitter input size)
766767
* All planes will be positioned inside this space,

drivers/gpu/drm/i915/display/intel_fbdev.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,11 @@ static int intelfb_create(struct drm_fb_helper *helper,
235235
info->apertures->ranges[0].base = ggtt->gmadr.start;
236236
info->apertures->ranges[0].size = ggtt->mappable_end;
237237

238+
/* Our framebuffer is the entirety of fbdev's system memory */
239+
info->fix.smem_start =
240+
(unsigned long)(ggtt->gmadr.start + vma->node.start);
241+
info->fix.smem_len = vma->node.size;
242+
238243
vaddr = i915_vma_pin_iomap(vma);
239244
if (IS_ERR(vaddr)) {
240245
DRM_ERROR("Failed to remap framebuffer into virtual memory\n");
@@ -244,10 +249,6 @@ static int intelfb_create(struct drm_fb_helper *helper,
244249
info->screen_base = vaddr;
245250
info->screen_size = vma->node.size;
246251

247-
/* Our framebuffer is the entirety of fbdev's system memory */
248-
info->fix.smem_start = (unsigned long)info->screen_base;
249-
info->fix.smem_len = info->screen_size;
250-
251252
drm_fb_helper_fill_info(info, &ifbdev->helper, sizes);
252253

253254
/* If the object is shmemfs backed, it will have given us zeroed pages.

drivers/gpu/drm/i915/gem/i915_gem_userptr.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -671,8 +671,28 @@ i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj,
671671
obj->mm.dirty = false;
672672

673673
for_each_sgt_page(page, sgt_iter, pages) {
674-
if (obj->mm.dirty)
674+
if (obj->mm.dirty && trylock_page(page)) {
675+
/*
676+
* As this may not be anonymous memory (e.g. shmem)
677+
* but exist on a real mapping, we have to lock
678+
* the page in order to dirty it -- holding
679+
* the page reference is not sufficient to
680+
* prevent the inode from being truncated.
681+
* Play safe and take the lock.
682+
*
683+
* However...!
684+
*
685+
* The mmu-notifier can be invalidated for a
686+
* migrate_page, that is alreadying holding the lock
687+
* on the page. Such a try_to_unmap() will result
688+
* in us calling put_pages() and so recursively try
689+
* to lock the page. We avoid that deadlock with
690+
* a trylock_page() and in exchange we risk missing
691+
* some page dirtying.
692+
*/
675693
set_page_dirty(page);
694+
unlock_page(page);
695+
}
676696

677697
mark_page_accessed(page);
678698
put_page(page);

drivers/gpu/drm/i915/gt/intel_engine_pool.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ node_create(struct intel_engine_pool *pool, size_t sz)
103103
return ERR_CAST(obj);
104104
}
105105

106+
i915_gem_object_set_readonly(obj);
107+
106108
node->obj = obj;
107109
return node;
108110
}

drivers/gpu/drm/i915/i915_pmu.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -843,8 +843,8 @@ create_event_attributes(struct i915_pmu *pmu)
843843
const char *name;
844844
const char *unit;
845845
} events[] = {
846-
__event(I915_PMU_ACTUAL_FREQUENCY, "actual-frequency", "MHz"),
847-
__event(I915_PMU_REQUESTED_FREQUENCY, "requested-frequency", "MHz"),
846+
__event(I915_PMU_ACTUAL_FREQUENCY, "actual-frequency", "M"),
847+
__event(I915_PMU_REQUESTED_FREQUENCY, "requested-frequency", "M"),
848848
__event(I915_PMU_INTERRUPTS, "interrupts", NULL),
849849
__event(I915_PMU_RC6_RESIDENCY, "rc6-residency", "ns"),
850850
};

drivers/gpu/drm/i915/i915_scheduler.c

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,37 @@ static inline int rq_prio(const struct i915_request *rq)
177177
return rq->sched.attr.priority | __NO_PREEMPTION;
178178
}
179179

180-
static void kick_submission(struct intel_engine_cs *engine, int prio)
180+
static inline bool need_preempt(int prio, int active)
181181
{
182-
const struct i915_request *inflight = *engine->execlists.active;
182+
/*
183+
* Allow preemption of low -> normal -> high, but we do
184+
* not allow low priority tasks to preempt other low priority
185+
* tasks under the impression that latency for low priority
186+
* tasks does not matter (as much as background throughput),
187+
* so kiss.
188+
*/
189+
return prio >= max(I915_PRIORITY_NORMAL, active);
190+
}
191+
192+
static void kick_submission(struct intel_engine_cs *engine,
193+
const struct i915_request *rq,
194+
int prio)
195+
{
196+
const struct i915_request *inflight;
197+
198+
/*
199+
* We only need to kick the tasklet once for the high priority
200+
* new context we add into the queue.
201+
*/
202+
if (prio <= engine->execlists.queue_priority_hint)
203+
return;
204+
205+
rcu_read_lock();
206+
207+
/* Nothing currently active? We're overdue for a submission! */
208+
inflight = execlists_active(&engine->execlists);
209+
if (!inflight)
210+
goto unlock;
183211

184212
/*
185213
* If we are already the currently executing context, don't
@@ -188,10 +216,15 @@ static void kick_submission(struct intel_engine_cs *engine, int prio)
188216
* tasklet, i.e. we have not change the priority queue
189217
* sufficiently to oust the running context.
190218
*/
191-
if (!inflight || !i915_scheduler_need_preempt(prio, rq_prio(inflight)))
192-
return;
219+
if (inflight->hw_context == rq->hw_context)
220+
goto unlock;
193221

194-
tasklet_hi_schedule(&engine->execlists.tasklet);
222+
engine->execlists.queue_priority_hint = prio;
223+
if (need_preempt(prio, rq_prio(inflight)))
224+
tasklet_hi_schedule(&engine->execlists.tasklet);
225+
226+
unlock:
227+
rcu_read_unlock();
195228
}
196229

197230
static void __i915_schedule(struct i915_sched_node *node,
@@ -317,13 +350,8 @@ static void __i915_schedule(struct i915_sched_node *node,
317350
list_move_tail(&node->link, cache.priolist);
318351
}
319352

320-
if (prio <= engine->execlists.queue_priority_hint)
321-
continue;
322-
323-
engine->execlists.queue_priority_hint = prio;
324-
325353
/* Defer (tasklet) submission until after all of our updates. */
326-
kick_submission(engine, prio);
354+
kick_submission(engine, node_to_request(node), prio);
327355
}
328356

329357
spin_unlock(&engine->active.lock);

0 commit comments

Comments
 (0)