[Nouveau] [Bug 49142] New: [NV4A] OpengGL content corruption when width = 2048
https://bugs.freedesktop.org/show_bug.cgi?id=49142 Bug #: 49142 Summary: [NV4A] OpengGL content corruption when width = 2048 Classification: Unclassified Product: Mesa Version: git Platform: Other OS/Version: All Status: NEW Severity: normal Priority: medium Component: Drivers/DRI/nouveau AssignedTo: nouveau@lists.freedesktop.org ReportedBy: michel.herm...@gmail.com When a window with opengl content with a width = 2048 the right part show random memory. Was easy to discover for me due since I'm using dual head with kwin opengl rendering. glxdemo produce the same corruption if enlarged enougth. Thought I was not really able to test if the same kind of problem appends with expending the height. Note that this is a regression in nv30 from nvfx. -- Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are the assignee for the bug. ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [Bug 49148] New: nv20_state_fb.c:50: get_rt_format: Assertion `0' failed.
https://bugs.freedesktop.org/show_bug.cgi?id=49148 Bug #: 49148 Summary: nv20_state_fb.c:50: get_rt_format: Assertion `0' failed. Classification: Unclassified Product: xorg Version: unspecified Platform: x86 (IA32) OS/Version: Linux (All) Status: NEW Severity: normal Priority: medium Component: Driver/nouveau AssignedTo: nouveau@lists.freedesktop.org ReportedBy: johndo...@rambler.ru QAContact: xorg-t...@lists.x.org Lubuntu 11.10 0.0 VGA compatible controller: nVidia Corporation NV25 [GeForce4 Ti 4400] (rev a3) X.Org version: 1.11.2.902 dimensions:1024x768 pixels (270x203 millimeters) depth of root window:24 planes direct rendering: Yes server glx vendor string: SGI server glx version string: 1.4 -- OpenGL vendor string: Nouveau OpenGL renderer string: Mesa DRI nv25 x86/MMX/SSE2 OpenGL version string: 1.2 Mesa 8.0.2 Linux 3.1.3-030103-generic xserver-xorg-video-nouveau 1:0.0.16+git20120328.ab7291d3-0ubuntu0sarvatt~oneiric Start of some 3D applications. Example SweetHome3D-3.3$ ./SweetHome3D JAVA 3D: OpenGL 1.2 detected; will run with reduced functionality JAVA 3D: OpenGL 1.2 detected; will run with reduced functionality java: nv20_state_fb.c:50: get_rt_format: Assertion `0' failed. -- Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are the assignee for the bug. ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [Bug 49148] nv20_state_fb.c:50: get_rt_format: Assertion `0' failed.
https://bugs.freedesktop.org/show_bug.cgi?id=49148 --- Comment #1 from Lucas Stach d...@lynxeye.de 2012-04-25 12:51:55 PDT --- Created attachment 60588 -- https://bugs.freedesktop.org/attachment.cgi?id=60588 proposed fix Could you please try the attached patch? It's only compile tested, as I don't have any vieux hardware and you have to compile mesa from git, but it should be worth a try. -- Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are the assignee for the bug. ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [Bug 48890] dmesg full of DATA_ERROR SEMANTIC_PTSZ_OVER_LIMIT errors on nouveau driver
https://bugs.freedesktop.org/show_bug.cgi?id=48890 --- Comment #6 from Alen Skondro askon...@gmail.com 2012-04-25 14:04:48 PDT --- Confirmed, there are no error messages anymore. Thank you! -- Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are the assignee for the bug. ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [PATCH v2 1/4] drm/nouveau: base fence timeout on time of emission
Wait loop can be interrupted by signal, so if signals are raised periodically (e.g. SIGALRM) this loop may never finish. Use emission time as a base for fence timeout. Signed-off-by: Marcin Slusarz marcin.slus...@gmail.com --- drivers/gpu/drm/nouveau/nouveau_fence.c |5 - 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index a22b9ad..41ee17d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -44,6 +44,7 @@ struct nouveau_fence { uint32_t sequence; bool signalled; + unsigned long timeout; void (*work)(void *priv, bool signalled); void *priv; @@ -172,6 +173,7 @@ nouveau_fence_emit(struct nouveau_fence *fence) } OUT_RING (chan, fence-sequence); FIRE_RING(chan); + fence-timeout = jiffies + 3 * DRM_HZ; return 0; } @@ -230,7 +232,8 @@ __nouveau_fence_signalled(void *sync_obj, void *sync_arg) int __nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) { - unsigned long timeout = jiffies + (3 * DRM_HZ); + struct nouveau_fence *fence = nouveau_fence(sync_obj); + unsigned long timeout = fence-timeout; unsigned long sleep_time = NSEC_PER_MSEC / 1000; ktime_t t; int ret = 0; -- 1.7.8.5 ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [PATCH v2 2/4] drm/nouveau: propagate errors from vm flushes
We need this for lockup recovery. Signed-off-by: Marcin Slusarz marcin.slus...@gmail.com --- drivers/gpu/drm/nouveau/nouveau_bo.c |9 +++-- drivers/gpu/drm/nouveau/nouveau_drv.h |6 +++--- drivers/gpu/drm/nouveau/nouveau_vm.c | 20 ++-- drivers/gpu/drm/nouveau/nouveau_vm.h | 18 +- drivers/gpu/drm/nouveau/nv50_fifo.c |4 ++-- drivers/gpu/drm/nouveau/nv50_graph.c | 12 drivers/gpu/drm/nouveau/nv50_mpeg.c |4 ++-- drivers/gpu/drm/nouveau/nv50_vm.c | 30 -- drivers/gpu/drm/nouveau/nv84_crypt.c |4 ++-- drivers/gpu/drm/nouveau/nva3_copy.c |4 ++-- drivers/gpu/drm/nouveau/nvc0_vm.c |3 ++- 11 files changed, 67 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 638ae32..5b0dc50 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1230,10 +1230,15 @@ nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nouveau_vm *vm, return ret; if (nvbo-bo.mem.mem_type == TTM_PL_VRAM) - nouveau_vm_map(vma, nvbo-bo.mem.mm_node); + ret = nouveau_vm_map(vma, nvbo-bo.mem.mm_node); else if (nvbo-bo.mem.mem_type == TTM_PL_TT) - nouveau_vm_map_sg(vma, 0, size, node); + ret = nouveau_vm_map_sg(vma, 0, size, node); + + if (ret) { + nouveau_vm_put(vma); + return ret; + } list_add_tail(vma-head, nvbo-vma_list); vma-refcount = 1; diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 2f8e80a..d120baf 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -320,7 +320,7 @@ struct nouveau_exec_engine { int (*object_new)(struct nouveau_channel *, int engine, u32 handle, u16 class); void (*set_tile_region)(struct drm_device *dev, int i); - void (*tlb_flush)(struct drm_device *, int engine); + int (*tlb_flush)(struct drm_device *, int engine); }; struct nouveau_instmem_engine { @@ -387,7 +387,7 @@ struct nouveau_fifo_engine { void (*destroy_context)(struct nouveau_channel *); int (*load_context)(struct nouveau_channel *); int (*unload_context)(struct drm_device *); - void (*tlb_flush)(struct drm_device *dev); + int (*tlb_flush)(struct drm_device *dev); }; struct nouveau_display_engine { @@ -1246,7 +1246,7 @@ extern int nv50_fifo_create_context(struct nouveau_channel *); extern void nv50_fifo_destroy_context(struct nouveau_channel *); extern int nv50_fifo_load_context(struct nouveau_channel *); extern int nv50_fifo_unload_context(struct drm_device *); -extern void nv50_fifo_tlb_flush(struct drm_device *dev); +extern int nv50_fifo_tlb_flush(struct drm_device *dev); /* nvc0_fifo.c */ extern int nvc0_fifo_init(struct drm_device *); diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.c b/drivers/gpu/drm/nouveau/nouveau_vm.c index 2bf6c03..e2d4853 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vm.c +++ b/drivers/gpu/drm/nouveau/nouveau_vm.c @@ -27,7 +27,7 @@ #include nouveau_mm.h #include nouveau_vm.h -void +int nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node) { struct nouveau_vm *vm = vma-vm; @@ -67,16 +67,16 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node) } } - vm-flush(vm); + return vm-flush(vm); } -void +int nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node) { - nouveau_vm_map_at(vma, 0, node); + return nouveau_vm_map_at(vma, 0, node); } -void +int nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, struct nouveau_mem *mem) { @@ -110,10 +110,10 @@ nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, } } - vm-flush(vm); + return vm-flush(vm); } -void +int nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length) { struct nouveau_vm *vm = vma-vm; @@ -144,13 +144,13 @@ nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length) } } - vm-flush(vm); + return vm-flush(vm); } -void +int nouveau_vm_unmap(struct nouveau_vma *vma) { - nouveau_vm_unmap_at(vma, 0, (u64)vma-node-length 12); + return nouveau_vm_unmap_at(vma, 0, (u64)vma-node-length 12); } static void diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.h b/drivers/gpu/drm/nouveau/nouveau_vm.h index 4fb6e72..59dc206 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vm.h +++ b/drivers/gpu/drm/nouveau/nouveau_vm.h @@ -73,7 +73,7 @@ struct nouveau_vm { void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *, struct nouveau_mem *, u32 pte, u32 cnt,
[Nouveau] [PATCH v2 3/4] drm/nv50: let applications hanging on vm flush to be killed
Signed-off-by: Marcin Slusarz marcin.slus...@gmail.com --- drivers/gpu/drm/nouveau/nv50_graph.c |5 + 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c index 6899547..a61853f 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c @@ -435,6 +435,11 @@ nv84_graph_tlb_flush(struct drm_device *dev, int engine) if ((tmp 7) == 1) idle = false; } + + if (fatal_signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } } while (!idle !(timeout = ptimer-read(dev) - start 20)); if (timeout) { -- 1.7.8.5 ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [PATCH v2 4/4] drm/nouveau: gpu lockup recovery
Overall idea: Detect lockups by watching for timeouts (vm flush / fence), return -EIOs, handle them at ioctl level, reset the GPU and repeat last ioctl. GPU reset is done by doing suspend / resume cycle with few tweaks: - CPU-only bo eviction - ignoring vm flush / fence timeouts - shortening waits Signed-off-by: Marcin Slusarz marcin.slus...@gmail.com --- drivers/gpu/drm/nouveau/Makefile |2 +- drivers/gpu/drm/nouveau/nouveau_bo.c |2 +- drivers/gpu/drm/nouveau/nouveau_channel.c |5 +- drivers/gpu/drm/nouveau/nouveau_drv.c | 56 ++- drivers/gpu/drm/nouveau/nouveau_drv.h | 45 - drivers/gpu/drm/nouveau/nouveau_fence.c|7 +- drivers/gpu/drm/nouveau/nouveau_gem.c | 14 +++- drivers/gpu/drm/nouveau/nouveau_notifier.c |3 + drivers/gpu/drm/nouveau/nouveau_object.c |6 + drivers/gpu/drm/nouveau/nouveau_reset.c| 148 drivers/gpu/drm/nouveau/nouveau_state.c|6 + drivers/gpu/drm/nouveau/nv50_graph.c | 11 +- 12 files changed, 290 insertions(+), 15 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nouveau_reset.c diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 03860f5..77d0c33 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -9,7 +9,7 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \ nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ - nouveau_hdmi.o nouveau_dp.o nouveau_ramht.o \ + nouveau_hdmi.o nouveau_dp.o nouveau_ramht.o nouveau_reset.o \ nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o \ nouveau_mm.o nouveau_vm.o nouveau_mxm.o nouveau_gpio.o \ nv04_timer.o \ diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 5b0dc50..7de6cad 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -936,7 +936,7 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, } /* Software copy if the card isn't up and running yet. */ - if (!dev_priv-channel) { + if (!dev_priv-channel || nouveau_gpu_reset_in_progress(dev_priv-dev)) { ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem); goto out; } diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index 846afb0..c0fa5a7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c @@ -420,7 +420,7 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, init-fb_ctxdma_handle, init-tt_ctxdma_handle); if (ret) - return ret; + goto out; init-channel = chan-id; if (nouveau_vram_pushbuf == 0) { @@ -450,6 +450,9 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, if (ret == 0) atomic_inc(chan-users); /* userspace reference */ nouveau_channel_put(chan); +out: + if (ret == -EIO) + ret = nouveau_reset_device(dev); return ret; } diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 090fff6..261e1f5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -237,7 +237,7 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) if (!dev_priv-eng[e]) continue; - ret = dev_priv-eng[e]-fini(dev, e, true); + ret = dev_priv-eng[e]-fini(dev, e, !nouveau_gpu_reset_in_progress(dev)); if (ret) { NV_ERROR(dev, ... engine %d failed: %d\n, e, ret); goto out_abort; @@ -443,11 +443,63 @@ nouveau_pci_resume(struct pci_dev *pdev) return 0; } +void intr_rwsem_init(struct intr_rwsem *r) +{ + init_rwsem(r-rwsem); + mutex_init(r-mutex); +} + +int intr_rwsem_down_read_interruptible(struct intr_rwsem *r) +{ + while (down_read_trylock(r-rwsem) == 0) { + int ret = mutex_lock_interruptible(r-mutex); + if (ret) + return ret; + mutex_unlock(r-mutex); + } + return 0; +} + +void intr_rwsem_up_read(struct intr_rwsem *r) +{ + up_read(r-rwsem); +} + +void intr_rwsem_down_write(struct intr_rwsem *r) +{ + mutex_lock(r-mutex); + down_write(r-rwsem); +} + +void intr_rwsem_up_write(struct intr_rwsem *r) +{ + up_write(r-rwsem); + mutex_unlock(r-mutex); +} + +static long nouveau_ioctl(struct file *filp, +
[Nouveau] [Bug 48890] dmesg full of DATA_ERROR SEMANTIC_PTSZ_OVER_LIMIT errors on nouveau driver
https://bugs.freedesktop.org/show_bug.cgi?id=48890 Lucas Stach d...@lynxeye.de changed: What|Removed |Added Status|NEW |RESOLVED Resolution||FIXED -- Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are the assignee for the bug. ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
Re: [Nouveau] [PATCH v2 4/4] drm/nouveau: gpu lockup recovery
On Wed, Apr 25, 2012 at 11:20:36PM +0200, Marcin Slusarz wrote: Overall idea: Detect lockups by watching for timeouts (vm flush / fence), return -EIOs, handle them at ioctl level, reset the GPU and repeat last ioctl. GPU reset is done by doing suspend / resume cycle with few tweaks: - CPU-only bo eviction - ignoring vm flush / fence timeouts - shortening waits Signed-off-by: Marcin Slusarz marcin.slus...@gmail.com --- What changed from v1: - moved ioctl locking from drm core to nouveau - made down_reads interruptible - fixed build bug on 32-bit systems ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [PATCH 1/2] drm/nouveau: Use drm_vblank_count_and_time() for pageflip completion events.
From: Mario Kleiner mario.klei...@tuebingen.mpg.de Emit kms pageflip completion events with proper vblank count and timestamp for the vblank interval in which the pageflip completed. This makes the timestamps and counts consistent with what the OML_sync_control spec defines. v2 Lucas Stach: rebased on top of nouveau tree and resolved trivial conflict. Signed-off-by: Mario Kleiner mario.klei...@tuebingen.mpg.de Conflicts: drivers/gpu/drm/nouveau/nouveau_display.c --- drivers/gpu/drm/nouveau/nouveau_display.c | 29 +++-- drivers/gpu/drm/nouveau/nouveau_drv.h |1 + 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 71379f8..2c0f415 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -504,7 +504,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, *s = (struct nouveau_page_flip_state) { { }, event, nouveau_crtc(crtc)-index, fb-bits_per_pixel, fb-pitches[0], crtc-x, crtc-y, - new_bo-bo.offset }; + new_bo-bo.offset, crtc-framedur_ns }; /* Choose the channel the flip will be handled in */ chan = nouveau_fence_channel(new_bo-bo.sync_obj); @@ -550,6 +550,9 @@ nouveau_finish_page_flip(struct nouveau_channel *chan, struct drm_device *dev = chan-dev; struct nouveau_page_flip_state *s; unsigned long flags; + struct timeval tnow, tvbl; + + do_gettimeofday(tnow); spin_lock_irqsave(dev-event_lock, flags); @@ -563,12 +566,26 @@ nouveau_finish_page_flip(struct nouveau_channel *chan, struct nouveau_page_flip_state, head); if (s-event) { struct drm_pending_vblank_event *e = s-event; - struct timeval now; - do_gettimeofday(now); - e-event.sequence = 0; - e-event.tv_sec = now.tv_sec; - e-event.tv_usec = now.tv_usec; + e-event.sequence = drm_vblank_count_and_time(dev, s-crtc, tvbl); + + /* Called before vblank count and timestamp have +* been updated for the vblank interval of flip +* completion? If so, need to increment vblank count and +* add one videorefresh duration to returned timestamp +* to account for this. We assume this happened if we +* get called over 0.9 frame durations after the last +* timestamped vblank. +*/ + if (10 * (timeval_to_ns(tnow) - timeval_to_ns(tvbl)) +9 * s-framedur_ns) { + e-event.sequence++; + tvbl = ns_to_timeval(timeval_to_ns(tvbl) + + s-framedur_ns); + } + + e-event.tv_sec = tvbl.tv_sec; + e-event.tv_usec = tvbl.tv_usec; list_add_tail(e-base.link, e-base.file_priv-event_list); wake_up_interruptible(e-base.file_priv-event_wait); } diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index ab9f9e0..ba10ad7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -203,6 +203,7 @@ struct nouveau_page_flip_state { struct drm_pending_vblank_event *event; int crtc, bpp, pitch, x, y; uint64_t offset; + s64 framedur_ns; }; enum nouveau_channel_mutex_class { -- 1.7.10 ___ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau
[Nouveau] [PATCH 2/2] drm/nouveau: implement precise vblank timestamping
This patch implements the driver hooks needed for precise vblank timestamping. This is a complementary patch to Mario Kleiner's patches to improve swap scheduling. With the complete patchset applied nouveau will be able to provide correct and precise pageflip timestamps (compliant to OML_sync_control spec) v2: - Rebase on top of nouveau tree and update to reflect Ben's review feedback. v3: - Split nv04+ and nv50+ paths into separate functions. - Do not advertise precise vblank timestamping on nvd9+, as it's not confirmed to work and the nv50 codepath may not work due to moved regs. Kudos to Mario for his many helpful comments and testing. Signed-off-by: Lucas Stach d...@lynxeye.de Reviewed-by: Mario Kleiner mario.klei...@tuebingen.mpg.de Tested-by: Mario Kleiner mario.klei...@tuebingen.mpg.de --- drivers/gpu/drm/nouveau/nouveau_display.c | 25 ++ drivers/gpu/drm/nouveau/nouveau_reg.h |9 +++- drivers/gpu/drm/nouveau/nv04_display.c| 55 ++ drivers/gpu/drm/nouveau/nv50_crtc.c | 19 drivers/gpu/drm/nouveau/nv50_display.c| 71 + drivers/gpu/drm/nouveau/nvreg.h |1 + 6 files changed, 179 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 2c0f415..810ba72 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -258,6 +258,27 @@ nouveau_display_fini(struct drm_device *dev) } int +nouveau_get_vblank_timestamp(struct drm_device *dev, int crtc, +int *max_error, struct timeval *vblank_time, +unsigned flags) +{ + struct drm_crtc *drmcrtc; + + if (crtc 0 || crtc = dev-num_crtcs) { + DRM_ERROR(Invalid crtc %d\n, crtc); + return -EINVAL; + } + + list_for_each_entry(drmcrtc, dev-mode_config.crtc_list, head) { + if(nouveau_crtc(drmcrtc)-index == crtc) + break; + } + + return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error, + vblank_time, flags, drmcrtc); +} + +int nouveau_display_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev-dev_private; @@ -327,6 +348,10 @@ nouveau_display_create(struct drm_device *dev) if (ret) goto disp_create_err; + if (dev-driver-get_scanout_position) + dev-driver-get_vblank_timestamp = + nouveau_get_vblank_timestamp; + if (dev-mode_config.num_crtc) { ret = drm_vblank_init(dev, dev-mode_config.num_crtc); if (ret) diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h index 43a96b9..0ec1945 100644 --- a/drivers/gpu/drm/nouveau/nouveau_reg.h +++ b/drivers/gpu/drm/nouveau/nouveau_reg.h @@ -762,7 +762,7 @@ #define NV50_PDISPLAY_CRTC_CLOCK 0x00610ad0 #define NV50_PDISPLAY_CRTC_COLOR_CTRL0x00610ae0 #define NV50_PDISPLAY_CRTC_SYNC_START_TO_BLANK_END 0x00610ae8 -#define NV50_PDISPLAY_CRTC_MODE_UNK1 0x00610af0 +#define NV50_PDISPLAY_CRTC_VBL_START 0x00610af0 #define NV50_PDISPLAY_CRTC_DISPLAY_TOTAL 0x00610af8 #define NV50_PDISPLAY_CRTC_SYNC_DURATION 0x00610b00 #define NV50_PDISPLAY_CRTC_MODE_UNK2 0x00610b08 @@ -800,6 +800,13 @@ #define NV50_PDISPLAY_SOR_CLK0x00614000 #define NV50_PDISPLAY_SOR_CLK_CTRL2(i) ((i) * 0x800 + 0x614300) +#define NV50_PDISPLAY_CRTC_STAT_VERT(i0) (0x00616340 + 0x800*(i0)) +#define NV50_PDISPLAY_CRTC_STAT_VERT_VLINE__MASK 0x +#define NV50_PDISPLAY_CRTC_STAT_VERT_VBLANK_COUNT__MASK 0x +#define NV50_PDISPLAY_CRTC_STAT_VERT_VBLANK_COUNT__SHIFT 16 +#define NV50_PDISPLAY_CRTC_STAT_HORZ(i0) (0x00616344 + 0x800*(i0)) +#define NV50_PDISPLAY_CRTC_STAT_HORZ_HLINE__MASK 0x + #define NV50_PDISPLAY_VGACRTC(r)((r) + 0x619400) #define NV50_PDISPLAY_DAC0x0061a000 diff --git a/drivers/gpu/drm/nouveau/nv04_display.c b/drivers/gpu/drm/nouveau/nv04_display.c index 7047d37..2622953 100644 --- a/drivers/gpu/drm/nouveau/nv04_display.c +++ b/drivers/gpu/drm/nouveau/nv04_display.c @@ -26,6 +26,7 @@ #include drm.h #include drm_crtc_helper.h +#include nouveau_crtc.h #include nouveau_drv.h #include nouveau_fb.h #include nouveau_hw.h @@ -35,6 +36,58 @@ static void nv04_vblank_crtc0_isr(struct drm_device *); static void nv04_vblank_crtc1_isr(struct drm_device *); +int