- 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 <airlied@redhat.com>
Unified · Split
| @@ -201,6 +201,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc) · 200 unmodified lines | ||
| 201 | 201 | crtc_state->update_wm_post = false; |
| 202 | 202 | crtc_state->fb_changed = false; |
| 203 | 203 | crtc_state->fifo_changed = false; |
| 204 | + crtc_state->preload_luts = false; | |
| 204 | 205 | crtc_state->wm.need_postvbl_update = false; |
| 205 | 206 | crtc_state->fb_bits = 0; |
| 206 | 207 | crtc_state->update_planes = 0; |
| @@ -990,6 +990,55 @@ void intel_color_commit(const struct intel_crtc_state *crtc_state) · 989 unmodified lines | ||
| 990 | 990 | dev_priv->display.color_commit(crtc_state); |
| 991 | 991 | } |
| 992 | 992 | |
| 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 | + | |
| 993 | 1042 | int intel_color_check(struct intel_crtc_state *crtc_state) |
| 994 | 1043 | { |
| 995 | 1044 | 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) · 137 unmodified lines | ||
| 1133 | 1182 | if (ret) |
| 1134 | 1183 | return ret; |
| 1135 | 1184 | |
| 1185 | + crtc_state->preload_luts = intel_can_preload_luts(crtc_state); | |
| 1186 | + | |
| 1136 | 1187 | return 0; |
| 1137 | 1188 | } |
| 1138 | 1189 | |
| @@ -1185,6 +1236,8 @@ static int chv_color_check(struct intel_crtc_state *crtc_state) · 46 unmodified lines | ||
| 1185 | 1236 | if (ret) |
| 1186 | 1237 | return ret; |
| 1187 | 1238 | |
| 1239 | + crtc_state->preload_luts = chv_can_preload_luts(crtc_state); | |
| 1240 | + | |
| 1188 | 1241 | return 0; |
| 1189 | 1242 | } |
| 1190 | 1243 | |
| @@ -1224,6 +1277,8 @@ static int ilk_color_check(struct intel_crtc_state *crtc_state) · 33 unmodified lines | ||
| 1224 | 1277 | if (ret) |
| 1225 | 1278 | return ret; |
| 1226 | 1279 | |
| 1280 | + crtc_state->preload_luts = intel_can_preload_luts(crtc_state); | |
| 1281 | + | |
| 1227 | 1282 | return 0; |
| 1228 | 1283 | } |
| 1229 | 1284 | |
| @@ -1281,6 +1336,8 @@ static int ivb_color_check(struct intel_crtc_state *crtc_state) · 51 unmodified lines | ||
| 1281 | 1336 | if (ret) |
| 1282 | 1337 | return ret; |
| 1283 | 1338 | |
| 1339 | + crtc_state->preload_luts = intel_can_preload_luts(crtc_state); | |
| 1340 | + | |
| 1284 | 1341 | return 0; |
| 1285 | 1342 | } |
| 1286 | 1343 | |
| @@ -1319,6 +1376,8 @@ static int glk_color_check(struct intel_crtc_state *crtc_state) · 32 unmodified lines | ||
| 1319 | 1376 | if (ret) |
| 1320 | 1377 | return ret; |
| 1321 | 1378 | |
| 1379 | + crtc_state->preload_luts = glk_can_preload_luts(crtc_state); | |
| 1380 | + | |
| 1322 | 1381 | return 0; |
| 1323 | 1382 | } |
| 1324 | 1383 | |
| @@ -1368,6 +1427,8 @@ static int icl_color_check(struct intel_crtc_state *crtc_state) · 43 unmodified lines | ||
| 1368 | 1427 | |
| 1369 | 1428 | crtc_state->csc_mode = icl_csc_mode(crtc_state); |
| 1370 | 1429 | |
| 1430 | + crtc_state->preload_luts = intel_can_preload_luts(crtc_state); | |
| 1431 | + | |
| 1371 | 1432 | return 0; |
| 1372 | 1433 | } |
| 1373 | 1434 | |
| @@ -2504,6 +2504,9 @@ u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv, · 2503 unmodified lines | ||
| 2504 | 2504 | * the highest stride limits of them all. |
| 2505 | 2505 | */ |
| 2506 | 2506 | crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_A); |
| 2507 | + if (!crtc) | |
| 2508 | + return 0; | |
| 2509 | + | |
| 2507 | 2510 | plane = to_intel_plane(crtc->base.primary); |
| 2508 | 2511 | |
| 2509 | 2512 | return plane->max_stride(plane, pixel_format, modifier, |
| @@ -13740,6 +13743,11 @@ static void intel_update_crtc(struct intel_crtc *crtc, · 11230 unmodified lines | ||
| 13740 | 13743 | /* vblanks work again, re-enable pipe CRC. */ |
| 13741 | 13744 | intel_crtc_enable_pipe_crc(crtc); |
| 13742 | 13745 | } 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 | + | |
| 13743 | 13751 | intel_pre_plane_update(old_crtc_state, new_crtc_state); |
| 13744 | 13752 | |
| 13745 | 13753 | if (new_crtc_state->update_pipe) |
| @@ -14034,6 +14042,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) · 288 unmodified lines | ||
| 14034 | 14042 | for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { |
| 14035 | 14043 | if (new_crtc_state->base.active && |
| 14036 | 14044 | !needs_modeset(new_crtc_state) && |
| 14045 | + !new_crtc_state->preload_luts && | |
| 14037 | 14046 | (new_crtc_state->base.color_mgmt_changed || |
| 14038 | 14047 | new_crtc_state->update_pipe)) |
| 14039 | 14048 | intel_color_load_luts(new_crtc_state); |
| @@ -761,6 +761,7 @@ struct intel_crtc_state { · 760 unmodified lines | ||
| 761 | 761 | bool update_wm_pre, update_wm_post; /* watermarks are updated */ |
| 762 | 762 | bool fb_changed; /* fb on any of the planes is changed */ |
| 763 | 763 | bool fifo_changed; /* FIFO split is changed */ |
| 764 | + bool preload_luts; | |
| 764 | 765 | |
| 765 | 766 | /* Pipe source size (ie. panel fitter input size) |
| 766 | 767 | * All planes will be positioned inside this space, |
| @@ -235,6 +235,11 @@ static int intelfb_create(struct drm_fb_helper *helper, · 234 unmodified lines | ||
| 235 | 235 | info->apertures->ranges[0].base = ggtt->gmadr.start; |
| 236 | 236 | info->apertures->ranges[0].size = ggtt->mappable_end; |
| 237 | 237 | |
| 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 | + | |
| 238 | 243 | vaddr = i915_vma_pin_iomap(vma); |
| 239 | 244 | if (IS_ERR(vaddr)) { |
| 240 | 245 | DRM_ERROR("Failed to remap framebuffer into virtual memory\n"); |
| @@ -244,10 +249,6 @@ static int intelfb_create(struct drm_fb_helper *helper, · 3 unmodified lines | ||
| 244 | 249 | info->screen_base = vaddr; |
| 245 | 250 | info->screen_size = vma->node.size; |
| 246 | 251 | |
| 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 | − | |
| 251 | 252 | drm_fb_helper_fill_info(info, &ifbdev->helper, sizes); |
| 252 | 253 | |
| 253 | 254 | /* If the object is shmemfs backed, it will have given us zeroed pages. |
| @@ -671,8 +671,28 @@ i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj, · 670 unmodified lines | ||
| 671 | 671 | obj->mm.dirty = false; |
| 672 | 672 | |
| 673 | 673 | 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 | + */ | |
| 675 | 693 | set_page_dirty(page); |
| 694 | + unlock_page(page); | |
| 695 | + } | |
| 676 | 696 | |
| 677 | 697 | mark_page_accessed(page); |
| 678 | 698 | put_page(page); |
| @@ -103,6 +103,8 @@ node_create(struct intel_engine_pool *pool, size_t sz) · 102 unmodified lines | ||
| 103 | 103 | return ERR_CAST(obj); |
| 104 | 104 | } |
| 105 | 105 | |
| 106 | + i915_gem_object_set_readonly(obj); | |
| 107 | + | |
| 106 | 108 | node->obj = obj; |
| 107 | 109 | return node; |
| 108 | 110 | } |
| @@ -843,8 +843,8 @@ create_event_attributes(struct i915_pmu *pmu) · 842 unmodified lines | ||
| 843 | 843 | const char *name; |
| 844 | 844 | const char *unit; |
| 845 | 845 | } 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"), | |
| 848 | 848 | __event(I915_PMU_INTERRUPTS, "interrupts", NULL), |
| 849 | 849 | __event(I915_PMU_RC6_RESIDENCY, "rc6-residency", "ns"), |
| 850 | 850 | }; |
| @@ -177,9 +177,37 @@ static inline int rq_prio(const struct i915_request *rq) · 176 unmodified lines | ||
| 177 | 177 | return rq->sched.attr.priority | __NO_PREEMPTION; |
| 178 | 178 | } |
| 179 | 179 | |
| 180 | −static void kick_submission(struct intel_engine_cs *engine, int prio) | |
| 180 | +static inline bool need_preempt(int prio, int active) | |
| 181 | 181 | { |
| 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; | |
| 183 | 211 | |
| 184 | 212 | /* |
| 185 | 213 | * 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) · 2 unmodified lines | ||
| 188 | 216 | * tasklet, i.e. we have not change the priority queue |
| 189 | 217 | * sufficiently to oust the running context. |
| 190 | 218 | */ |
| 191 | − if (!inflight || !i915_scheduler_need_preempt(prio, rq_prio(inflight))) | |
| 192 | − return; | |
| 219 | + if (inflight->hw_context == rq->hw_context) | |
| 220 | + goto unlock; | |
| 193 | 221 | |
| 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(); | |
| 195 | 228 | } |
| 196 | 229 | |
| 197 | 230 | static void __i915_schedule(struct i915_sched_node *node, |
| @@ -317,13 +350,8 @@ static void __i915_schedule(struct i915_sched_node *node, · 119 unmodified lines | ||
| 317 | 350 | list_move_tail(&node->link, cache.priolist); |
| 318 | 351 | } |
| 319 | 352 | |
| 320 | − if (prio <= engine->execlists.queue_priority_hint) | |
| 321 | − continue; | |
| 322 | − | |
| 323 | − engine->execlists.queue_priority_hint = prio; | |
| 324 | − | |
| 325 | 353 | /* Defer (tasklet) submission until after all of our updates. */ |
| 326 | − kick_submission(engine, prio); | |
| 354 | + kick_submission(engine, node_to_request(node), prio); | |
| 327 | 355 | } |
| 328 | 356 | |
| 329 | 357 | spin_unlock(&engine->active.lock); |