Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'drm-fixes-2019-12-28' of git://anongit.freedesktop.org/drm/drm

Pull drm fixes from Dave Airlie:
"Post-xmas food coma recovery fixes. Only three fixes for i915 since I
expect most people are holidaying.

i915:
- power management rc6 fix
- framebuffer tracking fix
- display power management ratelimit fix"

* tag 'drm-fixes-2019-12-28' of git://anongit.freedesktop.org/drm/drm:
drm/i915: Hold reference to intel_frontbuffer as we track activity
drm/i915/gt: Ratelimit display power w/a
drm/i915/pmu: Ensure monotonic rc6

+139 -86
+1 -1
drivers/gpu/drm/i915/display/intel_display.c
··· 15112 15112 return ret; 15113 15113 15114 15114 fb_obj_bump_render_priority(obj); 15115 - intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_DIRTYFB); 15115 + i915_gem_object_flush_frontbuffer(obj, ORIGIN_DIRTYFB); 15116 15116 15117 15117 if (!new_plane_state->base.fence) { /* implicit fencing */ 15118 15118 struct dma_fence *fence;
+6 -10
drivers/gpu/drm/i915/display/intel_frontbuffer.c
··· 229 229 vma->display_alignment = I915_GTT_MIN_ALIGNMENT; 230 230 spin_unlock(&obj->vma.lock); 231 231 232 - obj->frontbuffer = NULL; 232 + RCU_INIT_POINTER(obj->frontbuffer, NULL); 233 233 spin_unlock(&to_i915(obj->base.dev)->fb_tracking.lock); 234 234 235 235 i915_gem_object_put(obj); 236 - kfree(front); 236 + kfree_rcu(front, rcu); 237 237 } 238 238 239 239 struct intel_frontbuffer * ··· 242 242 struct drm_i915_private *i915 = to_i915(obj->base.dev); 243 243 struct intel_frontbuffer *front; 244 244 245 - spin_lock(&i915->fb_tracking.lock); 246 - front = obj->frontbuffer; 247 - if (front) 248 - kref_get(&front->ref); 249 - spin_unlock(&i915->fb_tracking.lock); 245 + front = __intel_frontbuffer_get(obj); 250 246 if (front) 251 247 return front; 252 248 ··· 258 262 i915_active_may_sleep(frontbuffer_retire)); 259 263 260 264 spin_lock(&i915->fb_tracking.lock); 261 - if (obj->frontbuffer) { 265 + if (rcu_access_pointer(obj->frontbuffer)) { 262 266 kfree(front); 263 - front = obj->frontbuffer; 267 + front = rcu_dereference_protected(obj->frontbuffer, true); 264 268 kref_get(&front->ref); 265 269 } else { 266 270 i915_gem_object_get(obj); 267 - obj->frontbuffer = front; 271 + rcu_assign_pointer(obj->frontbuffer, front); 268 272 } 269 273 spin_unlock(&i915->fb_tracking.lock); 270 274
+31 -3
drivers/gpu/drm/i915/display/intel_frontbuffer.h
··· 27 27 #include <linux/atomic.h> 28 28 #include <linux/kref.h> 29 29 30 + #include "gem/i915_gem_object_types.h" 30 31 #include "i915_active.h" 31 32 32 33 struct drm_i915_private; 33 - struct drm_i915_gem_object; 34 34 35 35 enum fb_op_origin { 36 36 ORIGIN_GTT, ··· 45 45 atomic_t bits; 46 46 struct i915_active write; 47 47 struct drm_i915_gem_object *obj; 48 + struct rcu_head rcu; 48 49 }; 49 50 50 51 void intel_frontbuffer_flip_prepare(struct drm_i915_private *i915, ··· 54 53 unsigned frontbuffer_bits); 55 54 void intel_frontbuffer_flip(struct drm_i915_private *i915, 56 55 unsigned frontbuffer_bits); 56 + 57 + void intel_frontbuffer_put(struct intel_frontbuffer *front); 58 + 59 + static inline struct intel_frontbuffer * 60 + __intel_frontbuffer_get(const struct drm_i915_gem_object *obj) 61 + { 62 + struct intel_frontbuffer *front; 63 + 64 + if (likely(!rcu_access_pointer(obj->frontbuffer))) 65 + return NULL; 66 + 67 + rcu_read_lock(); 68 + do { 69 + front = rcu_dereference(obj->frontbuffer); 70 + if (!front) 71 + break; 72 + 73 + if (unlikely(!kref_get_unless_zero(&front->ref))) 74 + continue; 75 + 76 + if (likely(front == rcu_access_pointer(obj->frontbuffer))) 77 + break; 78 + 79 + intel_frontbuffer_put(front); 80 + } while (1); 81 + rcu_read_unlock(); 82 + 83 + return front; 84 + } 57 85 58 86 struct intel_frontbuffer * 59 87 intel_frontbuffer_get(struct drm_i915_gem_object *obj); ··· 148 118 void intel_frontbuffer_track(struct intel_frontbuffer *old, 149 119 struct intel_frontbuffer *new, 150 120 unsigned int frontbuffer_bits); 151 - 152 - void intel_frontbuffer_put(struct intel_frontbuffer *front); 153 121 154 122 #endif /* __INTEL_FRONTBUFFER_H__ */
+13 -4
drivers/gpu/drm/i915/display/intel_overlay.c
··· 279 279 struct i915_vma *vma) 280 280 { 281 281 enum pipe pipe = overlay->crtc->pipe; 282 + struct intel_frontbuffer *from = NULL, *to = NULL; 282 283 283 284 WARN_ON(overlay->old_vma); 284 285 285 - intel_frontbuffer_track(overlay->vma ? overlay->vma->obj->frontbuffer : NULL, 286 - vma ? vma->obj->frontbuffer : NULL, 287 - INTEL_FRONTBUFFER_OVERLAY(pipe)); 286 + if (overlay->vma) 287 + from = intel_frontbuffer_get(overlay->vma->obj); 288 + if (vma) 289 + to = intel_frontbuffer_get(vma->obj); 290 + 291 + intel_frontbuffer_track(from, to, INTEL_FRONTBUFFER_OVERLAY(pipe)); 292 + 293 + if (to) 294 + intel_frontbuffer_put(to); 295 + if (from) 296 + intel_frontbuffer_put(from); 288 297 289 298 intel_frontbuffer_flip_prepare(overlay->i915, 290 299 INTEL_FRONTBUFFER_OVERLAY(pipe)); ··· 775 766 ret = PTR_ERR(vma); 776 767 goto out_pin_section; 777 768 } 778 - intel_frontbuffer_flush(new_bo->frontbuffer, ORIGIN_DIRTYFB); 769 + i915_gem_object_flush_frontbuffer(new_bo, ORIGIN_DIRTYFB); 779 770 780 771 if (!overlay->active) { 781 772 u32 oconfig;
+2 -1
drivers/gpu/drm/i915/gem/i915_gem_clflush.c
··· 20 20 { 21 21 GEM_BUG_ON(!i915_gem_object_has_pages(obj)); 22 22 drm_clflush_sg(obj->mm.pages); 23 - intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU); 23 + 24 + i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU); 24 25 } 25 26 26 27 static int clflush_work(struct dma_fence_work *base)
+2 -2
drivers/gpu/drm/i915/gem/i915_gem_domain.c
··· 664 664 i915_gem_object_unlock(obj); 665 665 666 666 if (write_domain) 667 - intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU); 667 + i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU); 668 668 669 669 out_unpin: 670 670 i915_gem_object_unpin_pages(obj); ··· 784 784 } 785 785 786 786 out: 787 - intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU); 787 + i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU); 788 788 obj->mm.dirty = true; 789 789 /* return with the pages pinned */ 790 790 return 0;
+25 -1
drivers/gpu/drm/i915/gem/i915_gem_object.c
··· 280 280 for_each_ggtt_vma(vma, obj) 281 281 intel_gt_flush_ggtt_writes(vma->vm->gt); 282 282 283 - intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU); 283 + i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU); 284 284 285 285 for_each_ggtt_vma(vma, obj) { 286 286 if (vma->iomap) ··· 306 306 } 307 307 308 308 obj->write_domain = 0; 309 + } 310 + 311 + void __i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj, 312 + enum fb_op_origin origin) 313 + { 314 + struct intel_frontbuffer *front; 315 + 316 + front = __intel_frontbuffer_get(obj); 317 + if (front) { 318 + intel_frontbuffer_flush(front, origin); 319 + intel_frontbuffer_put(front); 320 + } 321 + } 322 + 323 + void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj, 324 + enum fb_op_origin origin) 325 + { 326 + struct intel_frontbuffer *front; 327 + 328 + front = __intel_frontbuffer_get(obj); 329 + if (front) { 330 + intel_frontbuffer_invalidate(front, origin); 331 + intel_frontbuffer_put(front); 332 + } 309 333 } 310 334 311 335 void i915_gem_init__objects(struct drm_i915_private *i915)
+22 -1
drivers/gpu/drm/i915/gem/i915_gem_object.h
··· 13 13 14 14 #include <drm/i915_drm.h> 15 15 16 + #include "display/intel_frontbuffer.h" 16 17 #include "i915_gem_object_types.h" 17 - 18 18 #include "i915_gem_gtt.h" 19 19 20 20 void i915_gem_init__objects(struct drm_i915_private *i915); ··· 462 462 int i915_gem_object_wait_priority(struct drm_i915_gem_object *obj, 463 463 unsigned int flags, 464 464 const struct i915_sched_attr *attr); 465 + 466 + void __i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj, 467 + enum fb_op_origin origin); 468 + void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj, 469 + enum fb_op_origin origin); 470 + 471 + static inline void 472 + i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj, 473 + enum fb_op_origin origin) 474 + { 475 + if (unlikely(rcu_access_pointer(obj->frontbuffer))) 476 + __i915_gem_object_flush_frontbuffer(obj, origin); 477 + } 478 + 479 + static inline void 480 + i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj, 481 + enum fb_op_origin origin) 482 + { 483 + if (unlikely(rcu_access_pointer(obj->frontbuffer))) 484 + __i915_gem_object_invalidate_frontbuffer(obj, origin); 485 + } 465 486 466 487 #endif
+1 -1
drivers/gpu/drm/i915/gem/i915_gem_object_types.h
··· 150 150 */ 151 151 u16 write_domain; 152 152 153 - struct intel_frontbuffer *frontbuffer; 153 + struct intel_frontbuffer __rcu *frontbuffer; 154 154 155 155 /** Current tiling stride for the object, if it's tiled. */ 156 156 unsigned int tiling_and_stride;
+2 -1
drivers/gpu/drm/i915/gt/intel_gt_pm.c
··· 94 94 intel_uncore_forcewake_put(&i915->uncore, FORCEWAKE_ALL); 95 95 } 96 96 97 + /* Defer dropping the display power well for 100ms, it's slow! */ 97 98 GEM_BUG_ON(!wakeref); 98 - intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ, wakeref); 99 + intel_display_power_put_async(i915, POWER_DOMAIN_GT_IRQ, wakeref); 99 100 100 101 i915_globals_park(); 101 102
+5 -5
drivers/gpu/drm/i915/i915_gem.c
··· 161 161 * We manually control the domain here and pretend that it 162 162 * remains coherent i.e. in the GTT domain, like shmem_pwrite. 163 163 */ 164 - intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU); 164 + i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU); 165 165 166 166 if (copy_from_user(vaddr, user_data, args->size)) 167 167 return -EFAULT; ··· 169 169 drm_clflush_virt_range(vaddr, args->size); 170 170 intel_gt_chipset_flush(&to_i915(obj->base.dev)->gt); 171 171 172 - intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU); 172 + i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU); 173 173 return 0; 174 174 } 175 175 ··· 589 589 goto out_unpin; 590 590 } 591 591 592 - intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU); 592 + i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU); 593 593 594 594 user_data = u64_to_user_ptr(args->data_ptr); 595 595 offset = args->offset; ··· 631 631 user_data += page_length; 632 632 offset += page_length; 633 633 } 634 - intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU); 634 + i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU); 635 635 636 636 i915_gem_object_unlock_fence(obj, fence); 637 637 out_unpin: ··· 721 721 offset = 0; 722 722 } 723 723 724 - intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU); 724 + i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU); 725 725 i915_gem_object_unlock_fence(obj, fence); 726 726 727 727 return ret;
+20 -53
drivers/gpu/drm/i915/i915_pmu.c
··· 144 144 return ktime_to_ns(ktime_sub(ktime_get(), kt)); 145 145 } 146 146 147 - static u64 __pmu_estimate_rc6(struct i915_pmu *pmu) 148 - { 149 - u64 val; 150 - 151 - /* 152 - * We think we are runtime suspended. 153 - * 154 - * Report the delta from when the device was suspended to now, 155 - * on top of the last known real value, as the approximated RC6 156 - * counter value. 157 - */ 158 - val = ktime_since(pmu->sleep_last); 159 - val += pmu->sample[__I915_SAMPLE_RC6].cur; 160 - 161 - pmu->sample[__I915_SAMPLE_RC6_ESTIMATED].cur = val; 162 - 163 - return val; 164 - } 165 - 166 - static u64 __pmu_update_rc6(struct i915_pmu *pmu, u64 val) 167 - { 168 - /* 169 - * If we are coming back from being runtime suspended we must 170 - * be careful not to report a larger value than returned 171 - * previously. 172 - */ 173 - if (val >= pmu->sample[__I915_SAMPLE_RC6_ESTIMATED].cur) { 174 - pmu->sample[__I915_SAMPLE_RC6_ESTIMATED].cur = 0; 175 - pmu->sample[__I915_SAMPLE_RC6].cur = val; 176 - } else { 177 - val = pmu->sample[__I915_SAMPLE_RC6_ESTIMATED].cur; 178 - } 179 - 180 - return val; 181 - } 182 - 183 147 static u64 get_rc6(struct intel_gt *gt) 184 148 { 185 149 struct drm_i915_private *i915 = gt->i915; 186 150 struct i915_pmu *pmu = &i915->pmu; 187 151 unsigned long flags; 152 + bool awake = false; 188 153 u64 val; 189 154 190 - val = 0; 191 155 if (intel_gt_pm_get_if_awake(gt)) { 192 156 val = __get_rc6(gt); 193 157 intel_gt_pm_put_async(gt); 158 + awake = true; 194 159 } 195 160 196 161 spin_lock_irqsave(&pmu->lock, flags); 197 162 198 - if (val) 199 - val = __pmu_update_rc6(pmu, val); 163 + if (awake) { 164 + pmu->sample[__I915_SAMPLE_RC6].cur = val; 165 + } else { 166 + /* 167 + * We think we are runtime suspended. 168 + * 169 + * Report the delta from when the device was suspended to now, 170 + * on top of the last known real value, as the approximated RC6 171 + * counter value. 172 + */ 173 + val = ktime_since(pmu->sleep_last); 174 + val += pmu->sample[__I915_SAMPLE_RC6].cur; 175 + } 176 + 177 + if (val < pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur) 178 + val = pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur; 200 179 else 201 - val = __pmu_estimate_rc6(pmu); 180 + pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur = val; 202 181 203 182 spin_unlock_irqrestore(&pmu->lock, flags); 204 183 ··· 189 210 struct i915_pmu *pmu = &i915->pmu; 190 211 191 212 if (pmu->enable & config_enabled_mask(I915_PMU_RC6_RESIDENCY)) 192 - __pmu_update_rc6(pmu, __get_rc6(&i915->gt)); 213 + pmu->sample[__I915_SAMPLE_RC6].cur = __get_rc6(&i915->gt); 193 214 194 215 pmu->sleep_last = ktime_get(); 195 - } 196 - 197 - static void unpark_rc6(struct drm_i915_private *i915) 198 - { 199 - struct i915_pmu *pmu = &i915->pmu; 200 - 201 - /* Estimate how long we slept and accumulate that into rc6 counters */ 202 - if (pmu->enable & config_enabled_mask(I915_PMU_RC6_RESIDENCY)) 203 - __pmu_estimate_rc6(pmu); 204 216 } 205 217 206 218 #else ··· 202 232 } 203 233 204 234 static void park_rc6(struct drm_i915_private *i915) {} 205 - static void unpark_rc6(struct drm_i915_private *i915) {} 206 235 207 236 #endif 208 237 ··· 249 280 * Re-enable sampling timer when GPU goes active. 250 281 */ 251 282 __i915_pmu_maybe_start_timer(pmu); 252 - 253 - unpark_rc6(i915); 254 283 255 284 spin_unlock_irq(&pmu->lock); 256 285 }
+1 -1
drivers/gpu/drm/i915/i915_pmu.h
··· 18 18 __I915_SAMPLE_FREQ_ACT = 0, 19 19 __I915_SAMPLE_FREQ_REQ, 20 20 __I915_SAMPLE_RC6, 21 - __I915_SAMPLE_RC6_ESTIMATED, 21 + __I915_SAMPLE_RC6_LAST_REPORTED, 22 22 __I915_NUM_PMU_SAMPLERS 23 23 }; 24 24
+8 -2
drivers/gpu/drm/i915/i915_vma.c
··· 1104 1104 return err; 1105 1105 1106 1106 if (flags & EXEC_OBJECT_WRITE) { 1107 - if (intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CS)) 1108 - i915_active_add_request(&obj->frontbuffer->write, rq); 1107 + struct intel_frontbuffer *front; 1108 + 1109 + front = __intel_frontbuffer_get(obj); 1110 + if (unlikely(front)) { 1111 + if (intel_frontbuffer_invalidate(front, ORIGIN_CS)) 1112 + i915_active_add_request(&front->write, rq); 1113 + intel_frontbuffer_put(front); 1114 + } 1109 1115 1110 1116 dma_resv_add_excl_fence(vma->resv, &rq->fence); 1111 1117 obj->write_domain = I915_GEM_DOMAIN_RENDER;