You are not logged in.

#1 2020-01-15 10:39:29

zilverling
Member
From: Bennekom, Netherlands
Registered: 2009-08-19
Posts: 82

System freezes after moving mouse

This happens from time to time (once every few weeks): when I move my mouse, the system freezes. Desktop freezes, keyboard is dead, so I can't Ctrl-Alt out of the desktop into another terminal. Nothing. Need to restart my computer. Any ideas?

Processor: Intel N3700, microcode installed

$ dmesg | grep microcode
[    0.000000] microcode: microcode updated early to revision 0x368, date = 2019-04-23
[    1.518789] microcode: sig=0x406c3, pf=0x1, revision=0x368
[    1.519646] microcode: Microcode Update Driver: v2.2.

This is the tail of the journalctl output:

Jan 15 10:01:35 ------- rtkit-daemon[808]: Supervising 6 threads of 3 processes of 1 users.
Jan 15 10:01:35 ------- rtkit-daemon[808]: Supervising 6 threads of 3 processes of 1 users.
Jan 15 10:04:44 ------- rtkit-daemon[808]: Supervising 5 threads of 2 processes of 1 users.
Jan 15 10:04:44 ------- rtkit-daemon[808]: Supervising 5 threads of 2 processes of 1 users.
Jan 15 10:06:22 ------- rtkit-daemon[808]: Supervising 5 threads of 2 processes of 1 users.
Jan 15 10:06:22 ------- rtkit-daemon[808]: Supervising 5 threads of 2 processes of 1 users.
Jan 15 10:06:24 ------- kernel: perf: interrupt took too long (2529 > 2500), lowering kernel.perf_event_max_sample_rate to 78900
Jan 15 10:07:18 ------- systemd[1]: Starting Cleanup of Temporary Directories...
Jan 15 10:07:18 ------- systemd[1]: systemd-tmpfiles-clean.service: Succeeded.
Jan 15 10:07:18 ------- systemd[1]: Started Cleanup of Temporary Directories.
Jan 15 10:07:18 ------- audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=systemd-tmpfiles-clean comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
Jan 15 10:07:18 ------- audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=systemd-tmpfiles-clean comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
Jan 15 10:07:18 ------- kernel: audit: type=1130 audit(1579079238.275:45): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=systemd-tmpfiles-clean comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
Jan 15 10:07:18 ------- kernel: audit: type=1131 audit(1579079238.275:46): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=systemd-tmpfiles-clean comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
Jan 15 10:10:13 ------- kernel: perf: interrupt took too long (3199 > 3161), lowering kernel.perf_event_max_sample_rate to 62400
Jan 15 10:10:34 ------- rtkit-daemon[808]: Supervising 5 threads of 2 processes of 1 users.
Jan 15 10:10:34 ------- rtkit-daemon[808]: Supervising 5 threads of 2 processes of 1 users.
Jan 15 10:20:36 ------- rtkit-daemon[808]: Supervising 5 threads of 2 processes of 1 users.
Jan 15 10:20:36 ------- rtkit-daemon[808]: Supervising 5 threads of 2 processes of 1 users.
Jan 15 10:24:48 ------- systemd-networkd[285]: enp3s0: DHCPv6 address fd72:f05:cfe3::fd0/128 timeout preferred -1 valid -1
Jan 15 10:24:48 ------- systemd-networkd[285]: enp3s0: DHCPv6 address 2001:985:d31:fc::fd0/128 timeout preferred 2644 valid 6244
Jan 15 10:25:18 ------- kernel: perf: interrupt took too long (4004 > 3998), lowering kernel.perf_event_max_sample_rate to 49800

Offline

#2 2020-01-15 12:50:05

Lone_Wolf
Member
From: Netherlands, Europe
Registered: 2005-10-04
Posts: 11,911

Re: System freezes after moving mouse

Usually kernel: perf: interrupt took too long messages are considered harmless, but they can be the result of hardware/software troubles.

When the "freeze" happens, does the system come back after some time (say 30 minutes) ?

Are there clues that the system may be under heavy load ?
Drive activity leds, fans spinning hard, case getting hot etc

Does the numlock led on the keyboard change when you press numlock ?

Please post 2 full journal ouputs : one from a boot where the problem happened and from a normal boot. .


Disliking systemd intensely, but not satisfied with alternatives so focusing on taming systemd.


(A works at time B)  && (time C > time B ) ≠  (A works at time C)

Offline

#3 2020-01-23 12:02:57

zilverling
Member
From: Bennekom, Netherlands
Registered: 2009-08-19
Posts: 82

Re: System freezes after moving mouse

Thanks for your reaction @lone_wolf. I hadn't subscribed to this topic, so I only see your message now, after my system froze again this morning when moving the mouse while opening a tab in Firefox.

The tail of the log seems a bit more interesting than last week:

Jan 23 10:30:51 xxxxx kernel: BUG: kernel NULL pointer dereference, address: 0000000000000040
Jan 23 10:30:51 xxxxx kernel: #PF: supervisor read access in kernel mode
Jan 23 10:30:51 xxxxx kernel: #PF: error_code(0x0000) - not-present page
Jan 23 10:30:51 xxxxx kernel: PGD 0 P4D 0 
Jan 23 10:30:51 xxxxx kernel: Oops: 0000 [#1] PREEMPT SMP PTI
Jan 23 10:30:51 xxxxx kernel: CPU: 2 PID: 762 Comm: xfwm4 Not tainted 5.4.13-arch1-1 #1
Jan 23 10:30:51 xxxxx kernel: Hardware name: To Be Filled By O.E.M. To Be Filled By O.E.M./N3700-ITX, BIOS P2.00 04/16/2018
Jan 23 10:30:51 xxxxx kernel: RIP: 0010:i915_active_acquire+0x9/0x70 [i915]
Jan 23 10:30:51 xxxxx kernel: Code: 00 00 00 48 c7 46 58 00 00 00 00 c7 46 38 00 00 00 00 48 c7 c6 12 13 ca c0 e9 43 ce 16 e8 0f 1f 00 0f 1f 44 00 00 41 54 55 53 <8b> 47 38 48 89 fb 85 c0 74 15 8d 50 01 f0 0f b1 53 38 75 f2 45 31
Jan 23 10:30:51 xxxxx kernel: RSP: 0018:ffffa798c140ba48 EFLAGS: 00010292
Jan 23 10:30:51 xxxxx kernel: RAX: 0000000000000000 RBX: ffff9327d2531d40 RCX: 0000000000000000
Jan 23 10:30:51 xxxxx kernel: RDX: ffff9327d2531d40 RSI: ffff9327eafeb540 RDI: 0000000000000008
Jan 23 10:30:51 xxxxx kernel: RBP: ffff9327eafeb540 R08: ffff9327de123720 R09: ffff9327982ff300
Jan 23 10:30:51 xxxxx kernel: R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000008
Jan 23 10:30:51 xxxxx kernel: R13: 0000000000000004 R14: ffff9327de123600 R15: 0000000040000004
Jan 23 10:30:51 xxxxx kernel: FS:  00007fe14a078980(0000) GS:ffff9327f0300000(0000) knlGS:0000000000000000
Jan 23 10:30:51 xxxxx kernel: CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
Jan 23 10:30:51 xxxxx kernel: CR2: 0000000000000040 CR3: 000000044e360000 CR4: 00000000001006e0
Jan 23 10:30:51 xxxxx kernel: Call Trace:
Jan 23 10:30:51 xxxxx kernel:  i915_active_ref+0x21/0x1e0 [i915]
Jan 23 10:30:51 xxxxx kernel:  ? _raw_spin_lock+0x13/0x30
Jan 23 10:30:51 xxxxx kernel:  i915_vma_move_to_active+0x6e/0xf0 [i915]
Jan 23 10:30:51 xxxxx kernel:  i915_gem_do_execbuffer+0xc59/0x1520 [i915]
Jan 23 10:30:51 xxxxx kernel:  i915_gem_execbuffer2_ioctl+0x1df/0x3d0 [i915]
Jan 23 10:30:51 xxxxx kernel:  ? _raw_spin_lock_irqsave+0x26/0x50
Jan 23 10:30:51 xxxxx kernel:  ? i915_gem_execbuffer_ioctl+0x2e0/0x2e0 [i915]
Jan 23 10:30:51 xxxxx kernel:  drm_ioctl_kernel+0xb2/0x100 [drm]
Jan 23 10:30:51 xxxxx kernel:  drm_ioctl+0x209/0x360 [drm]
Jan 23 10:30:51 xxxxx kernel:  ? i915_gem_execbuffer_ioctl+0x2e0/0x2e0 [i915]
Jan 23 10:30:51 xxxxx kernel:  do_vfs_ioctl+0x43d/0x6c0
Jan 23 10:30:51 xxxxx kernel:  ksys_ioctl+0x5e/0x90
Jan 23 10:30:51 xxxxx kernel:  __x64_sys_ioctl+0x16/0x20
Jan 23 10:30:51 xxxxx kernel:  do_syscall_64+0x4e/0x140
Jan 23 10:30:51 xxxxx kernel:  entry_SYSCALL_64_after_hwframe+0x44/0xa9
Jan 23 10:30:51 xxxxx kernel: RIP: 0033:0x7fe14b07225b
Jan 23 10:30:51 xxxxx kernel: Code: 0f 1e fa 48 8b 05 25 9c 0c 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d f5 9b 0c 00 f7 d8 64 89 01 48
Jan 23 10:30:51 xxxxx kernel: RSP: 002b:00007ffc63f7fcd8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
Jan 23 10:30:51 xxxxx kernel: RAX: ffffffffffffffda RBX: 00007ffc63f7fd20 RCX: 00007fe14b07225b
Jan 23 10:30:51 xxxxx kernel: RDX: 00007ffc63f7fd20 RSI: 0000000040406469 RDI: 000000000000000a
Jan 23 10:30:51 xxxxx kernel: RBP: 0000000040406469 R08: 000055d79eaf4400 R09: 00007fe1487a6010
Jan 23 10:30:51 xxxxx kernel: R10: 0000000000000000 R11: 0000000000000246 R12: 000055d79eeaed80
Jan 23 10:30:51 xxxxx kernel: R13: 000000000000000a R14: ffffffffffffffff R15: 00007fe143f33468
Jan 23 10:30:51 xxxxx kernel: Modules linked in: fuse intel_rapl_msr intel_rapl_common intel_powerclamp coretemp snd_hda_codec_hdmi kvm_intel snd_hda_codec_realtek snd_hda_codec_generic ledtrig_audio kvm intel_spi_platform i915 intel_spi irqbypass spi_nor mei_hdcp mtd nls_iso8859_1 nls_cp437 i2c_algo_bit vfat crct10dif_pclmul fat crc32_pclmul iTCO_wdt iTCO_vendor_support drm_kms_helper uvcvideo videobuf2_vmalloc ghash_clmulni_intel videobuf2_memops videobuf2_v4l2 snd_hda_intel videobuf2_common snd_usb_audio snd_intel_nhlt snd_hda_codec videodev snd_usbmidi_lib aesni_intel drm snd_hda_core snd_hwdep r8169 hci_uart snd_rawmidi crypto_simd mousedev input_leds snd_seq_device snd_pcm realtek cryptd btqca glue_helper mc usblp snd_timer intel_cstate btrtl libphy pcspkr intel_gtt i2c_i801 snd agpgart btbcm lpc_ich intel_xhci_usb_role_switch btintel mei_txe syscopyarea sysfillrect mei bluetooth soundcore roles sysimgblt fb_sys_fops ecdh_generic rfkill_gpio i2c_hid ecc rfkill evdev mac_hid pwm_lpss_platform pwm_lpss
Jan 23 10:30:51 xxxxx kernel:  intel_int0002_vgpio ip_tables x_tables ext4 crc32c_generic crc16 mbcache jbd2 sd_mod hid_generic usbhid hid ahci libahci libata xhci_pci xhci_hcd crc32c_intel scsi_mod
Jan 23 10:30:51 xxxxx kernel: CR2: 0000000000000040
Jan 23 10:30:51 xxxxx kernel: ---[ end trace b8fc343edce10de7 ]---
Jan 23 10:30:51 xxxxx kernel: RIP: 0010:i915_active_acquire+0x9/0x70 [i915]
Jan 23 10:30:51 xxxxx kernel: Code: 00 00 00 48 c7 46 58 00 00 00 00 c7 46 38 00 00 00 00 48 c7 c6 12 13 ca c0 e9 43 ce 16 e8 0f 1f 00 0f 1f 44 00 00 41 54 55 53 <8b> 47 38 48 89 fb 85 c0 74 15 8d 50 01 f0 0f b1 53 38 75 f2 45 31
Jan 23 10:30:51 xxxxx kernel: RSP: 0018:ffffa798c140ba48 EFLAGS: 00010292
Jan 23 10:30:51 xxxxx kernel: RAX: 0000000000000000 RBX: ffff9327d2531d40 RCX: 0000000000000000
Jan 23 10:30:51 xxxxx kernel: RDX: ffff9327d2531d40 RSI: ffff9327eafeb540 RDI: 0000000000000008
Jan 23 10:30:51 xxxxx kernel: RBP: ffff9327eafeb540 R08: ffff9327de123720 R09: ffff9327982ff300
Jan 23 10:30:51 xxxxx kernel: R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000008
Jan 23 10:30:51 xxxxx kernel: R13: 0000000000000004 R14: ffff9327de123600 R15: 0000000040000004
Jan 23 10:30:51 xxxxx kernel: FS:  00007fe14a078980(0000) GS:ffff9327f0300000(0000) knlGS:0000000000000000
Jan 23 10:30:51 xxxxx kernel: CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
Jan 23 10:30:51 xxxxx kernel: CR2: 00007f32f4699760 CR3: 000000044e360000 CR4: 00000000001006e0

Last edited by zilverling (2020-01-23 12:03:48)

Offline

#4 2020-01-23 12:22:38

loqs
Member
Registered: 2014-03-06
Posts: 17,315

Re: System freezes after moving mouse

https://lore.kernel.org/stable/15783126 … kroah.com/

First attempt at backporting patch to v5.4.Y

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index af50f05f4e9d..746777f848cb 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -14429,7 +14429,7 @@ intel_prepare_plane_fb(struct drm_plane *plane,
 		return ret;
 
 	fb_obj_bump_render_priority(obj);
-	intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_DIRTYFB);
+	i915_gem_object_flush_frontbuffer(obj, ORIGIN_DIRTYFB);
 
 	if (!new_state->fence) { /* implicit fencing */
 		struct dma_fence *fence;
diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.c b/drivers/gpu/drm/i915/display/intel_frontbuffer.c
index 719379774fa5..66ff8dee856c 100644
--- a/drivers/gpu/drm/i915/display/intel_frontbuffer.c
+++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.c
@@ -224,8 +224,8 @@ static void frontbuffer_release(struct kref *ref)
 	front->obj->frontbuffer = NULL;
 	spin_unlock(&to_i915(front->obj->base.dev)->fb_tracking.lock);
 
-	i915_gem_object_put(front->obj);
-	kfree(front);
+	RCU_INIT_POINTER(obj->frontbuffer, NULL);
+	kfree_rcu(front, rcu);
 }
 
 struct intel_frontbuffer *
@@ -234,11 +234,7 @@ intel_frontbuffer_get(struct drm_i915_gem_object *obj)
 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
 	struct intel_frontbuffer *front;
 
-	spin_lock(&i915->fb_tracking.lock);
-	front = obj->frontbuffer;
-	if (front)
-		kref_get(&front->ref);
-	spin_unlock(&i915->fb_tracking.lock);
+	front = __intel_frontbuffer_get(obj);
 	if (front)
 		return front;
 
@@ -253,13 +249,13 @@ intel_frontbuffer_get(struct drm_i915_gem_object *obj)
 			 frontbuffer_active, frontbuffer_retire);
 
 	spin_lock(&i915->fb_tracking.lock);
-	if (obj->frontbuffer) {
+	if (rcu_access_pointer(obj->frontbuffer)) {
 		kfree(front);
-		front = obj->frontbuffer;
+		front = rcu_dereference_protected(obj->frontbuffer, true);
 		kref_get(&front->ref);
 	} else {
 		i915_gem_object_get(obj);
-		obj->frontbuffer = front;
+		rcu_assign_pointer(obj->frontbuffer, front);
 	}
 	spin_unlock(&i915->fb_tracking.lock);
 
diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.h b/drivers/gpu/drm/i915/display/intel_frontbuffer.h
index adc64d61a4a5..6d41f5394425 100644
--- a/drivers/gpu/drm/i915/display/intel_frontbuffer.h
+++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.h
@@ -27,10 +27,10 @@
 #include <linux/atomic.h>
 #include <linux/kref.h>
 
+#include "gem/i915_gem_object_types.h"
 #include "i915_active.h"
 
 struct drm_i915_private;
-struct drm_i915_gem_object;
 
 enum fb_op_origin {
 	ORIGIN_GTT,
@@ -45,6 +45,7 @@ struct intel_frontbuffer {
 	atomic_t bits;
 	struct i915_active write;
 	struct drm_i915_gem_object *obj;
+	struct rcu_head rcu;
 };
 
 void intel_frontbuffer_flip_prepare(struct drm_i915_private *i915,
@@ -54,6 +55,35 @@ void intel_frontbuffer_flip_complete(struct drm_i915_private *i915,
 void intel_frontbuffer_flip(struct drm_i915_private *i915,
 			    unsigned frontbuffer_bits);
 
+void intel_frontbuffer_put(struct intel_frontbuffer *front);
+
+static inline struct intel_frontbuffer *
+__intel_frontbuffer_get(const struct drm_i915_gem_object *obj)
+{
+	struct intel_frontbuffer *front;
+
+	if (likely(!rcu_access_pointer(obj->frontbuffer)))
+		return NULL;
+
+	rcu_read_lock();
+	do {
+		front = rcu_dereference(obj->frontbuffer);
+		if (!front)
+			break;
+
+		if (unlikely(!kref_get_unless_zero(&front->ref)))
+			continue;
+
+		if (likely(front == rcu_access_pointer(obj->frontbuffer)))
+			break;
+
+		intel_frontbuffer_put(front);
+	} while (1);
+	rcu_read_unlock();
+
+	return front;
+}
+
 struct intel_frontbuffer *
 intel_frontbuffer_get(struct drm_i915_gem_object *obj);
 
@@ -119,6 +149,4 @@ void intel_frontbuffer_track(struct intel_frontbuffer *old,
 			     struct intel_frontbuffer *new,
 			     unsigned int frontbuffer_bits);
 
-void intel_frontbuffer_put(struct intel_frontbuffer *front);
-
 #endif /* __INTEL_FRONTBUFFER_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c
index 29edfc343716..c754be02c1cc 100644
--- a/drivers/gpu/drm/i915/display/intel_overlay.c
+++ b/drivers/gpu/drm/i915/display/intel_overlay.c
@@ -278,12 +278,21 @@ static void intel_overlay_flip_prepare(struct intel_overlay *overlay,
 				       struct i915_vma *vma)
 {
 	enum pipe pipe = overlay->crtc->pipe;
+	struct intel_frontbuffer *from = NULL, *to = NULL;
 
 	WARN_ON(overlay->old_vma);
 
-	intel_frontbuffer_track(overlay->vma ? overlay->vma->obj->frontbuffer : NULL,
-				vma ? vma->obj->frontbuffer : NULL,
-				INTEL_FRONTBUFFER_OVERLAY(pipe));
+	if (overlay->vma)
+		from = intel_frontbuffer_get(overlay->vma->obj);
+	if (vma)
+		to = intel_frontbuffer_get(vma->obj);
+
+	intel_frontbuffer_track(from, to, INTEL_FRONTBUFFER_OVERLAY(pipe));
+
+	if (to)
+		intel_frontbuffer_put(to);
+	if (from)
+		intel_frontbuffer_put(from);
 
 	intel_frontbuffer_flip_prepare(overlay->i915,
 				       INTEL_FRONTBUFFER_OVERLAY(pipe));
@@ -768,7 +777,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
 		ret = PTR_ERR(vma);
 		goto out_pin_section;
 	}
-	intel_frontbuffer_flush(new_bo->frontbuffer, ORIGIN_DIRTYFB);
+	i915_gem_object_flush_frontbuffer(new_bo, ORIGIN_DIRTYFB);
 
 	if (!overlay->active) {
 		u32 oconfig;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c
index b9f504ba3b32..18ee708585a9 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c
@@ -20,7 +20,8 @@ static void __do_clflush(struct drm_i915_gem_object *obj)
 {
 	GEM_BUG_ON(!i915_gem_object_has_pages(obj));
 	drm_clflush_sg(obj->mm.pages);
-	intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
+
+	i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
 }
 
 static int clflush_work(struct dma_fence_work *base)
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c
index 9c58e8fac1d9..19c68f1d27ed 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c
@@ -674,7 +674,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
 	i915_gem_object_unlock(obj);
 
 	if (write_domain)
-		intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
+		i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);
 
 out_unpin:
 	i915_gem_object_unpin_pages(obj);
@@ -794,7 +794,7 @@ int i915_gem_object_prepare_write(struct drm_i915_gem_object *obj,
 	}
 
 out:
-	intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
+	i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);
 	obj->mm.dirty = true;
 	/* return with the pages pinned */
 	return 0;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index d7855dc5a5c5..c3b3f3f73256 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -270,7 +270,7 @@ i915_gem_object_flush_write_domain(struct drm_i915_gem_object *obj,
 		for_each_ggtt_vma(vma, obj)
 			intel_gt_flush_ggtt_writes(vma->vm->gt);
 
-		intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
+		i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
 
 		for_each_ggtt_vma(vma, obj) {
 			if (vma->iomap)
@@ -298,6 +298,30 @@ i915_gem_object_flush_write_domain(struct drm_i915_gem_object *obj,
 	obj->write_domain = 0;
 }
 
+void __i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj,
+					 enum fb_op_origin origin)
+{
+	struct intel_frontbuffer *front;
+
+	front = __intel_frontbuffer_get(obj);
+	if (front) {
+		intel_frontbuffer_flush(front, origin);
+		intel_frontbuffer_put(front);
+	}
+}
+
+void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
+					      enum fb_op_origin origin)
+{
+	struct intel_frontbuffer *front;
+
+	front = __intel_frontbuffer_get(obj);
+	if (front) {
+		intel_frontbuffer_invalidate(front, origin);
+		intel_frontbuffer_put(front);
+	}
+}
+
 void i915_gem_init__objects(struct drm_i915_private *i915)
 {
 	INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index ddf3605bea8e..53172a4185da 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -13,8 +13,8 @@
 
 #include <drm/i915_drm.h>
 
+#include "display/intel_frontbuffer.h"
 #include "i915_gem_object_types.h"
-
 #include "i915_gem_gtt.h"
 
 void i915_gem_init__objects(struct drm_i915_private *i915);
@@ -431,4 +431,25 @@ int i915_gem_object_wait_priority(struct drm_i915_gem_object *obj,
 				  const struct i915_sched_attr *attr);
 #define I915_PRIORITY_DISPLAY I915_USER_PRIORITY(I915_PRIORITY_MAX)
 
+void __i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj,
+					 enum fb_op_origin origin);
+void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
+					      enum fb_op_origin origin);
+
+static inline void
+i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj,
+				  enum fb_op_origin origin)
+{
+	if (unlikely(rcu_access_pointer(obj->frontbuffer)))
+		__i915_gem_object_flush_frontbuffer(obj, origin);
+}
+
+static inline void
+i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
+				       enum fb_op_origin origin)
+{
+	if (unlikely(rcu_access_pointer(obj->frontbuffer)))
+		__i915_gem_object_invalidate_frontbuffer(obj, origin);
+}
+
 #endif
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
index 646859fea224..b8b6abcf5bdc 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
@@ -143,7 +143,7 @@ struct drm_i915_gem_object {
 	 */
 	u16 write_domain;
 
-	struct intel_frontbuffer *frontbuffer;
+	struct intel_frontbuffer __rcu *frontbuffer;
 
 	/** Current tiling stride for the object, if it's tiled. */
 	unsigned int tiling_and_stride;
diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c
index 4949b5ad860f..cb8e76f046a1 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -471,12 +471,6 @@ lrc_descriptor(struct intel_context *ce, struct intel_engine_cs *engine)
 	return desc;
 }
 
-static void unwind_wa_tail(struct i915_request *rq)
-{
-	rq->tail = intel_ring_wrap(rq->ring, rq->wa_tail - WA_TAIL_BYTES);
-	assert_ring_tail_valid(rq->ring, rq->tail);
-}
-
 static struct i915_request *
 __unwind_incomplete_requests(struct intel_engine_cs *engine)
 {
@@ -495,7 +489,6 @@ __unwind_incomplete_requests(struct intel_engine_cs *engine)
 			continue; /* XXX */
 
 		__i915_request_unsubmit(rq);
-		unwind_wa_tail(rq);
 
 		/*
 		 * Push the request back into the queue for later resubmission.
@@ -514,6 +507,8 @@ __unwind_incomplete_requests(struct intel_engine_cs *engine)
 			GEM_BUG_ON(RB_EMPTY_ROOT(&engine->execlists.queue.rb_root));
 
 			list_move(&rq->sched.link, pl);
+			set_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags);
+
 			active = rq;
 		} else {
 			/*
@@ -650,13 +645,29 @@ execlists_schedule_out(struct i915_request *rq)
 	i915_request_put(rq);
 }
 
-static u64 execlists_update_context(const struct i915_request *rq)
+static u64 execlists_update_context(struct i915_request *rq)
 {
 	struct intel_context *ce = rq->hw_context;
-	u64 desc;
+	u64 desc = ce->lrc_desc;
+	u32 tail;
 
-	ce->lrc_reg_state[CTX_RING_TAIL + 1] =
-		intel_ring_set_tail(rq->ring, rq->tail);
+	/*
+	 * WaIdleLiteRestore:bdw,skl
+	 *
+	 * We should never submit the context with the same RING_TAIL twice
+	 * just in case we submit an empty ring, which confuses the HW.
+	 *
+	 * We append a couple of NOOPs (gen8_emit_wa_tail) after the end of
+	 * the normal request to be able to always advance the RING_TAIL on
+	 * subsequent resubmissions (for lite restore). Should that fail us,
+	 * and we try and submit the same tail again, force the context
+	 * reload.
+	 */
+	tail = intel_ring_set_tail(rq->ring, rq->tail);
+	if (unlikely(ce->lrc_reg_state[CTX_RING_TAIL + 1] == tail))
+		desc |= CTX_DESC_FORCE_RESTORE;
+	ce->lrc_reg_state[CTX_RING_TAIL + 1] = tail;
+	rq->tail = rq->wa_tail;
 
 	/*
 	 * Make sure the context image is complete before we submit it to HW.
@@ -675,7 +686,6 @@ static u64 execlists_update_context(const struct i915_request *rq)
 	 */
 	mb();
 
-	desc = ce->lrc_desc;
 	ce->lrc_desc &= ~CTX_DESC_FORCE_RESTORE;
 
 	return desc;
@@ -1150,16 +1160,6 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
 			if (!list_is_last(&last->sched.link,
 					  &engine->active.requests))
 				return;
-
-			/*
-			 * WaIdleLiteRestore:bdw,skl
-			 * Apply the wa NOOPs to prevent
-			 * ring:HEAD == rq:TAIL as we resubmit the
-			 * request. See gen8_emit_fini_breadcrumb() for
-			 * where we prepare the padding after the
-			 * end of the request.
-			 */
-			last->tail = last->wa_tail;
 		}
 	}
 
@@ -1651,11 +1651,12 @@ static void execlists_submission_timer(struct timer_list *timer)
 }
 
 static void queue_request(struct intel_engine_cs *engine,
-			  struct i915_sched_node *node,
-			  int prio)
+			  struct i915_request *rq)
 {
-	GEM_BUG_ON(!list_empty(&node->link));
-	list_add_tail(&node->link, i915_sched_lookup_priolist(engine, prio));
+	GEM_BUG_ON(!list_empty(&rq->sched.link));
+	list_add_tail(&rq->sched.link,
+		      i915_sched_lookup_priolist(engine, rq_prio(rq)));
+	set_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags);
 }
 
 static void __submit_queue_imm(struct intel_engine_cs *engine)
@@ -1691,7 +1692,7 @@ static void execlists_submit_request(struct i915_request *request)
 	/* Will be called from irq-context when using foreign fences. */
 	spin_lock_irqsave(&engine->active.lock, flags);
 
-	queue_request(engine, &request->sched, rq_prio(request));
+	queue_request(engine, request);
 
 	GEM_BUG_ON(RB_EMPTY_ROOT(&engine->execlists.queue.rb_root));
 	GEM_BUG_ON(list_empty(&request->sched.link));
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 98305d987ac1..1846675bf65a 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -143,7 +143,7 @@ i915_gem_phys_pwrite(struct drm_i915_gem_object *obj,
 	 * We manually control the domain here and pretend that it
 	 * remains coherent i.e. in the GTT domain, like shmem_pwrite.
 	 */
-	intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
+	i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);
 
 	if (copy_from_user(vaddr, user_data, args->size))
 		return -EFAULT;
@@ -151,7 +151,7 @@ i915_gem_phys_pwrite(struct drm_i915_gem_object *obj,
 	drm_clflush_virt_range(vaddr, args->size);
 	intel_gt_chipset_flush(&to_i915(obj->base.dev)->gt);
 
-	intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
+	i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
 	return 0;
 }
 
@@ -588,7 +588,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
 		goto out_unpin;
 	}
 
-	intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
+	i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);
 
 	user_data = u64_to_user_ptr(args->data_ptr);
 	offset = args->offset;
@@ -630,7 +630,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
 		user_data += page_length;
 		offset += page_length;
 	}
-	intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
+	i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
 
 	i915_gem_object_unlock_fence(obj, fence);
 out_unpin:
@@ -723,7 +723,7 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj,
 		offset = 0;
 	}
 
-	intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
+	i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
 	i915_gem_object_unlock_fence(obj, fence);
 
 	return ret;
diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c
index 1c5506822dc7..199be050db0d 100644
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
@@ -442,8 +442,10 @@ bool __i915_request_submit(struct i915_request *request)
 xfer:	/* We may be recursing from the signal callback of another i915 fence */
 	spin_lock_nested(&request->lock, SINGLE_DEPTH_NESTING);
 
-	if (!test_and_set_bit(I915_FENCE_FLAG_ACTIVE, &request->fence.flags))
+	if (!test_and_set_bit(I915_FENCE_FLAG_ACTIVE, &request->fence.flags)) {
 		list_move_tail(&request->sched.link, &engine->active.requests);
+		clear_bit(I915_FENCE_FLAG_PQUEUE, &request->fence.flags);
+	}
 
 	if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags) &&
 	    !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &request->fence.flags) &&
diff --git a/drivers/gpu/drm/i915/i915_request.h b/drivers/gpu/drm/i915/i915_request.h
index e4dd013761e8..79c87b3bde75 100644
--- a/drivers/gpu/drm/i915/i915_request.h
+++ b/drivers/gpu/drm/i915/i915_request.h
@@ -63,6 +63,18 @@ enum {
 	 */
 	I915_FENCE_FLAG_ACTIVE = DMA_FENCE_FLAG_USER_BITS,
 
+	/*
+	 * I915_FENCE_FLAG_PQUEUE - this request is ready for execution
+	 *
+	 * Using the scheduler, when a request is ready for execution it is put
+	 * into the priority queue, and removed from that queue when transferred
+	 * to the HW runlists. We want to track its membership within the
+	 * priority queue so that we can easily check before rescheduling.
+	 *
+	 * See i915_request_in_priority_queue()
+	 */
+	I915_FENCE_FLAG_PQUEUE,
+
 	/*
 	 * I915_FENCE_FLAG_SIGNAL - this request is currently on signal_list
 	 *
@@ -325,6 +337,11 @@ static inline bool i915_request_is_active(const struct i915_request *rq)
 	return test_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags);
 }
 
+static inline bool i915_request_in_priority_queue(const struct i915_request *rq)
+{
+	return test_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags);
+}
+
 /**
  * Returns true if seq1 is later than seq2.
  */
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
index 3eba8a2b39c2..c970656544d9 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -329,20 +329,18 @@ static void __i915_schedule(struct i915_sched_node *node,
 
 		node->attr.priority = prio;
 
-		if (list_empty(&node->link)) {
-			/*
-			 * If the request is not in the priolist queue because
-			 * it is not yet runnable, then it doesn't contribute
-			 * to our preemption decisions. On the other hand,
-			 * if the request is on the HW, it too is not in the
-			 * queue; but in that case we may still need to reorder
-			 * the inflight requests.
-			 */
+		/*
+		 * Once the request is ready, it will be placed into the
+		 * priority lists and then onto the HW runlist. Before the
+		 * request is ready, it does not contribute to our preemption
+		 * decisions and we can safely ignore it, as it will, and
+		 * any preemption required, be dealt with upon submission.
+		 * See engine->submit_request()
+		 */
+		if (list_empty(&node->link))
 			continue;
-		}
 
-		if (!intel_engine_is_virtual(engine) &&
-		    !i915_request_is_active(node_to_request(node))) {
+		if (i915_request_in_priority_queue(node_to_request(node))) {
 			if (!cache.priolist)
 				cache.priolist =
 					i915_sched_lookup_priolist(engine,
diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
index e0e677b2a3a9..057b6f705c1f 100644
--- a/drivers/gpu/drm/i915/i915_vma.c
+++ b/drivers/gpu/drm/i915/i915_vma.c
@@ -907,10 +907,14 @@ int i915_vma_move_to_active(struct i915_vma *vma,
 		return err;
 
 	if (flags & EXEC_OBJECT_WRITE) {
-		if (intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CS))
-			i915_active_ref(&obj->frontbuffer->write,
-					rq->timeline,
-					rq);
+		struct intel_frontbuffer *front;
+
+		front = __intel_frontbuffer_get(obj);
+		if (unlikely(front)) {
+			if (intel_frontbuffer_invalidate(front, ORIGIN_CS))
+				i915_active_add_request(&front->write, rq);
+			intel_frontbuffer_put(front);
+		}
 
 		dma_resv_add_excl_fence(vma->resv, &rq->fence);
 		obj->write_domain = I915_GEM_DOMAIN_RENDER;

Edit:
The original fix is in v5.5-rc4+

Last edited by loqs (2020-01-23 12:43:46)

Offline

Board footer

Powered by FluxBB