drm/vmwgfx: Add a cpu blit utility that can be used for page-backed bos
Subsystems (3)
PATCH 1/11 drm/vmwgfx: Add a cpu blit utility that can be used for page-backed bos
The utility uses kmap_atomic() instead of vmapping the whole buffer object. As a result there will be more book-keeping but on some architectures this will help avoid exhausting vmalloc space and also avoid expensive TLB flushes.
The blit utility also adds a provision to compute a bounding box of changed content, which is very useful to optimize presentation speed of ill-behaved applications that don't supply proper damage regions, and for page-flips. The cost of computing the bounding box is not that expensive when done in a cpu-blit utility like this.
--- drivers/gpu/drm/vmwgfx/Makefile | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_blit.c | 506 +++++++++++++++++++++++++++++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 48 ++++ 3 files changed, 555 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
drivers/gpu/drm/vmwgfx/Makefile +1 -1
@@ -7,6 +7,6 @@ vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \ vmwgfx_surface.o vmwgfx_prime.o vmwgfx_mob.o vmwgfx_shader.o \ vmwgfx_cmdbuf_res.o vmwgfx_cmdbuf.o vmwgfx_stdu.o \ vmwgfx_cotable.o vmwgfx_so.o vmwgfx_binding.o vmwgfx_msg.o \ - vmwgfx_simple_resource.o vmwgfx_va.o + vmwgfx_simple_resource.o vmwgfx_va.o vmwgfx_blit.o obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o
drivers/gpu/drm/vmwgfx/vmwgfx_blit.c new file +506 -0
506 lines not on this page · raw message
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +48 -0
60 lines not on this page · raw message
Signature · 6 lines
2.14.3 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 2/11 drm/vmwgfx: Use the cpu blit utility for framebuffer to screen target blits
This blit was previously performed using two large vmaps, one of which was teared down and remapped on each blit. Use the more resource- conserving TTM cpu blit instead.
The blit is used in boundary-box computing mode which makes it possible to minimize the bounding box used in host operations.
--- drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c | 23 ++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 50 ++++++++++------ drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 5 +- drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 105 +++++++++++---------------------- 6 files changed, 97 insertions(+), 91 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c +23 -0
@@ -185,6 +185,22 @@ static const struct ttm_place evictable_placement_flags[] = { } }; +static const struct ttm_place nonfixed_placement_flags[] = { + { + .fpfn =0 , + .lpfn =0 , + .flags =TTM_PL_FLAG_SYSTEM |TTM_PL_FLAG_CACHED + }, { + .fpfn =0 , + .lpfn =0 , + .flags =VMW_PL_FLAG_GMR |TTM_PL_FLAG_CACHED + }, { + .fpfn =0 , + .lpfn =0 , + .flags =VMW_PL_FLAG_MOB |TTM_PL_FLAG_CACHED + } +}; +struct ttm_placement vmw_evictable_placement = { .num_placement =4 , .placement = evictable_placement_flags,
@@ -213,6 +229,13 @@ struct ttm_placement vmw_mob_ne_placement = { .busy_placement = &mob_ne_placement_flags }; +struct ttm_placement vmw_nonfixed_placement = { + .num_placement =3 , + .placement = nonfixed_placement_flags, + .num_busy_placement =1 , + .busy_placement = &sys_placement_flags +}; +struct vmw_ttm_tt {struct ttm_dma_tt dma_ttm;struct vmw_private *dev_priv;
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +1 -0
@@ -767,6 +767,7 @@ extern struct ttm_placement vmw_evictable_placement;extern struct ttm_placement vmw_srf_placement;extern struct ttm_placement vmw_mob_placement;extern struct ttm_placement vmw_mob_ne_placement; +extern struct ttm_placement vmw_nonfixed_placement;extern struct ttm_bo_driver vmw_bo_driver;extern int vmw_dma_quiescent (struct drm_device *dev);extern int vmw_bo_map_dma (struct ttm_buffer_object *bo);
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +32 -18
97 lines not on this page · raw message
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +2 -2
@@ -177,7 +177,6 @@ struct vmw_plane_state {int pinned;/* For CPU Blit */ -struct ttm_bo_kmap_obj host_map;unsigned int cpp; };
@@ -289,7 +288,8 @@ int vmw_kms_helper_dirty(struct vmw_private *dev_priv,int vmw_kms_helper_buffer_prepare (struct vmw_private *dev_priv,struct vmw_dma_buffer *buf,bool interruptible, -bool validate_as_mob); +bool validate_as_mob, +bool for_cpu_blit);void vmw_kms_helper_buffer_revert (struct vmw_dma_buffer *buf); void vmw_kms_helper_buffer_finish(struct vmw_private *dev_priv, struct drm_file *file_priv,
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +3 -2
@@ -1032,7 +1032,7 @@ int vmw_kms_sou_do_dmabuf_dirty(struct vmw_private *dev_priv,int ret; ret =vmw_kms_helper_buffer_prepare (dev_priv, buf, interruptible, - false); + false, false);if (ret)return ret;
@@ -1130,7 +1130,8 @@ int vmw_kms_sou_readback(struct vmw_private *dev_priv,struct vmw_kms_dirty dirty;int ret; - ret =vmw_kms_helper_buffer_prepare (dev_priv, buf, true, false); + ret =vmw_kms_helper_buffer_prepare (dev_priv, buf, true, false, + false);if (ret)return ret;
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +36 -69
180 lines not on this page · raw message
Signature · 6 lines
2.14.3 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 3/11 drm/vmwgfx: Fix multiple command buffer context use
In reply to Thomas HellstromThe start / stop and preempt commands don't honor the context argument but rather acts on all available contexts.
Also add detection for context 1 availability.
Note that currently there's no driver interface for submitting buffers using the high-priority command queue (context 1).
Testing done:
Change the default context for command submission to 1 instead of 0, verify basic desktop functionality including faulty command injection and recovery.
--- drivers/gpu/drm/vmwgfx/device_include/svga_reg.h | 12 ++++- drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c | 57 +++++++++++------------- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 2 + 3 files changed, 38 insertions(+), 33 deletions(-)
drivers/gpu/drm/vmwgfx/device_include/svga_reg.h +11 -1
@@ -372,6 +372,14 @@ SVGAGuestPtr;* PA, not biased by the offset. When the command buffer is finished * the guest should not read the offset field as there is no guarantee * what it will set to. +* +* When the SVGA_CAP_HP_CMD_QUEUE cap bit is set a new command queue +* SVGA_CB_CONTEXT_1 is available. Commands submitted to this queue +* will be executed as quickly as possible by the SVGA device +* potentially before already queued commands on SVGA_CB_CONTEXT_0. +* The SVGA device guarantees that any command buffers submitted to +* SVGA_CB_CONTEXT_0 will be executed after any _already_ submitted +* command buffers to SVGA_CB_CONTEXT_1. */ #define SVGA_CB_MAX_SIZE (512 * 1024)/* 512 KB */
@@ -382,7 +390,8 @@ SVGAGuestPtr;typedef enum {SVGA_CB_CONTEXT_DEVICE =0x3f ,SVGA_CB_CONTEXT_0 =0x0 , -SVGA_CB_CONTEXT_MAX =0x1 , +SVGA_CB_CONTEXT_1 =0x1 ,/* Supported with SVGA_CAP_HP_CMD_QUEUE */ +SVGA_CB_CONTEXT_MAX =0x2 , }SVGACBContext ;
@@ -689,6 +698,7 @@ SVGASignedPoint;#define SVGA_CAP_CMD_BUFFERS_2 0x04000000#define SVGA_CAP_GBOBJECTS 0x08000000#define SVGA_CAP_DX 0x10000000 +#define SVGA_CAP_HP_CMD_QUEUE 0x20000000#define SVGA_CAP_CMD_RESERVED 0x80000000
drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c +25 -32
134 lines not on this page · raw message
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +2 -0
@@ -301,6 +301,8 @@ static void vmw_print_capabilities(uint32_t capabilities)DRM_INFO (" Guest Backed Resources.\n" );if (capabilities &SVGA_CAP_DX )DRM_INFO (" DX Features.\n" ); +if (capabilities &SVGA_CAP_HP_CMD_QUEUE ) +DRM_INFO (" HP Command Queue.\n" ); }/**
Signature · 6 lines
2.14.3 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 4/11 drm/vmwgfx: Avoid pinning fbdev framebuffers
In reply to Thomas Hellstromfbdev framebuffers were previously pinned to be able to keep them mapped across updates.
This commit introduces a mechanism that instead revalidates the map on each update, keeping the map cached across updates. The cached map is torn down if the underlying pages change. Typically on buffer object moves and swapouts.
This should be nicer to the system when we have resource contention.
Testing done: Basic fbdev functionality under Fedora 27.
--- drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c | 51 ++++++++++++++++++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 5 +++ drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 67 +++++++++----------------------- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 23 +++++++++++ 5 files changed, 98 insertions(+), 49 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c +1 -0
@@ -864,6 +864,7 @@ static void vmw_move_notify(struct ttm_buffer_object *bo,*/ static void vmw_swap_notify (struct ttm_buffer_object *bo) { +vmw_resource_swap_notify (bo); (void )ttm_bo_wait (bo, false, false); }
drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c +51 -0
54 lines not on this page · raw message
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +5 -0
@@ -92,6 +92,8 @@ struct vmw_dma_buffer {s32 pin_count;/* Not ref-counted. Protected by binding_mutex */ struct vmw_resource *dx_query_ctx; +/* Protected by reservation */ +struct ttm_bo_kmap_obj map; };/**
@@ -673,6 +675,7 @@ extern void vmw_resource_move_notify(struct ttm_buffer_object *bo, struct ttm_mem_reg *mem);extern void vmw_query_move_notify (struct ttm_buffer_object *bo,struct ttm_mem_reg *mem); +extern void vmw_resource_swap_notify (struct ttm_buffer_object *bo);extern int vmw_query_readback_all (struct vmw_dma_buffer *dx_query_mob);extern void vmw_fence_single_bo (struct ttm_buffer_object *bo,struct vmw_fence_obj *fence);
@@ -701,6 +704,8 @@ extern int vmw_dmabuf_unpin(struct vmw_private *vmw_priv,extern void vmw_bo_get_guest_ptr (const struct ttm_buffer_object *buf,SVGAGuestPtr *ptr);extern void vmw_bo_pin_reserved (struct vmw_dma_buffer *bo,bool pin); +extern void *vmw_dma_buffer_map_and_cache (struct vmw_dma_buffer *vbo); +extern void vmw_dma_buffer_unmap (struct vmw_dma_buffer *vbo);/** * Misc Ioctl functionality - vmwgfx_ioctl.c
drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +18 -49
117 lines not on this page · raw message
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +23 -0
@@ -354,6 +354,7 @@ void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo) {struct vmw_dma_buffer *vmw_bo =vmw_dma_buffer (bo); +vmw_dma_buffer_unmap (vmw_bo);kfree (vmw_bo); }
@@ -361,6 +362,7 @@ static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo) {struct vmw_user_dma_buffer *vmw_user_bo =vmw_user_dma_buffer (bo); +vmw_dma_buffer_unmap (&vmw_user_bo->dma);ttm_prime_object_kfree (vmw_user_bo, prime); }
@@ -1239,6 +1241,12 @@ void vmw_resource_move_notify(struct ttm_buffer_object *bo, dma_buf = container_of(bo, struct vmw_dma_buffer, base); +/* +* Kill any cached kernel maps before move. An optimization could +* be to do this iff source or destination memory type is VRAM. +*/ +vmw_dma_buffer_unmap (dma_buf); +if (mem->mem_type !=VMW_PL_MOB ) {struct vmw_resource *res, *n;struct ttm_validate_buffer val_buf;
@@ -1262,6 +1270,21 @@ void vmw_resource_move_notify(struct ttm_buffer_object *bo, } +/** +* vmw_resource_swap_notify - swapout notify callback. +* +* @bo: The buffer object to be swapped out. +*/ +void vmw_resource_swap_notify (struct ttm_buffer_object *bo) +{ +if (bo->destroy != vmw_dmabuf_bo_free && + bo->destroy != vmw_user_dmabuf_destroy) +return ; + +/* Kill any cached kernel maps before swapout */ +vmw_dma_buffer_unmap (vmw_dma_buffer (bo)); +} +/** * vmw_query_readback_all - Read back cached query states
Signature · 6 lines
2.14.3 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 5/11 drm/vmwgfx: Improve on hibernation
In reply to Thomas HellstromMake it possible to hibernate also with masters that don't switch VT at hibernation time. We save and restore modesetting state unless fbdev is active and enabled at hibernation time.
--- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 75 +++++++++++++++++++++++++------------ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 5 +++ drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 35 ++++++++++++----- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 48 ++++++++++++++++++++++++ 4 files changed, 130 insertions(+), 33 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +52 -23
@@ -1279,8 +1279,7 @@ static void vmw_master_drop(struct drm_device *dev,ttm_lock_set_kill (&dev_priv->fbdev_master.lock, false,SIGTERM );ttm_vt_unlock (&dev_priv->fbdev_master.lock); -if (dev_priv->enable_fb) -vmw_fb_on (dev_priv); +vmw_fb_refresh (dev_priv); }/**
@@ -1370,28 +1369,23 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,switch (val) {case PM_HIBERNATION_PREPARE : -if (dev_priv->enable_fb) -vmw_fb_off (dev_priv); -ttm_suspend_lock (&dev_priv->reservation_sem); -/* -* This empties VRAM and unbinds all GMR bindings. -* Buffer contents is moved to swappable memory. +* Take the reservation sem in write mode, which will make sure +* there are no other processes holding a buffer object +* reservation, meaning we should be able to evict all buffer +* objects if needed. +* Once user-space processes have been frozen, we can release +* the lock again. */ -vmw_execbuf_release_pinned_bo (dev_priv); -vmw_resource_evict_all (dev_priv); -vmw_release_device_early (dev_priv); -ttm_bo_swapout_all (&dev_priv->bdev); -vmw_fence_fifo_down (dev_priv->fman); +ttm_suspend_lock (&dev_priv->reservation_sem); + dev_priv->suspend_locked = true;break ;case PM_POST_HIBERNATION :case PM_POST_RESTORE : -vmw_fence_fifo_up (dev_priv->fman); -ttm_suspend_unlock (&dev_priv->reservation_sem); -if (dev_priv->enable_fb) -vmw_fb_on (dev_priv); -break ; -case PM_RESTORE_PREPARE : +if (READ_ONCE (dev_priv->suspend_locked)) { + dev_priv->suspend_locked = false; +ttm_suspend_unlock (&dev_priv->reservation_sem); + }break ;default :break ;
@@ -1442,25 +1436,50 @@ static int vmw_pm_freeze(struct device *kdev)struct pci_dev *pdev =to_pci_dev (kdev);struct drm_device *dev =pci_get_drvdata (pdev);struct vmw_private *dev_priv =vmw_priv (dev); +int ret; +/* +* Unlock for vmw_kms_suspend. +* No user-space processes should be running now. +*/ +ttm_suspend_unlock (&dev_priv->reservation_sem); + ret =vmw_kms_suspend (dev_priv->dev); +if (ret) { +ttm_suspend_lock (&dev_priv->reservation_sem); +DRM_ERROR ("Failed to freeze modesetting.\n" ); +return ret; + } dev_priv->suspended = true;if (dev_priv->enable_fb) -vmw_fifo_resource_dec (dev_priv); +vmw_fb_off (dev_priv); +ttm_suspend_lock (&dev_priv->reservation_sem); +vmw_execbuf_release_pinned_bo (dev_priv); +vmw_resource_evict_all (dev_priv); +vmw_release_device_early (dev_priv); +ttm_bo_swapout_all (&dev_priv->bdev); +if (dev_priv->enable_fb) +vmw_fifo_resource_dec (dev_priv);if (atomic_read (&dev_priv->num_fifo_resources) !=0 ) {DRM_ERROR ("Can't hibernate while 3D resources are active.\n" );if (dev_priv->enable_fb)vmw_fifo_resource_inc (dev_priv);WARN_ON (vmw_request_device_late (dev_priv)); + dev_priv->suspend_locked = false; +ttm_suspend_unlock (&dev_priv->reservation_sem); +if (dev_priv->suspend_state) +vmw_kms_resume (dev); +if (dev_priv->enable_fb) +vmw_fb_on (dev_priv); dev_priv->suspended = false; +vmw_fb_refresh (dev_priv);return -EBUSY ; } -if (dev_priv->enable_fb) -__vmw_svga_disable (dev_priv); +vmw_fence_fifo_down (dev_priv->fman); +__vmw_svga_disable (dev_priv);vmw_release_device_late (dev_priv); -return 0 ; }
@@ -1484,7 +1503,17 @@ static int vmw_pm_restore(struct device *kdev)if (dev_priv->enable_fb)__vmw_svga_enable (dev_priv); +vmw_fence_fifo_up (dev_priv->fman); + dev_priv->suspend_locked = false; +ttm_suspend_unlock (&dev_priv->reservation_sem); +if (dev_priv->suspend_state) +vmw_kms_resume (dev_priv->dev); + +if (dev_priv->enable_fb) +vmw_fb_on (dev_priv); + dev_priv->suspended = false; +vmw_fb_refresh (dev_priv);return 0 ; }
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +5 -0
@@ -425,6 +425,7 @@ struct vmw_private {struct vmw_framebuffer *implicit_fb;struct mutex global_kms_state_mutex;spinlock_t cursor_lock; +struct drm_atomic_state *suspend_state;/* * Context and surface management.
@@ -498,6 +499,7 @@ struct vmw_private {struct notifier_block pm_nb;bool suspended;bool refuse_hibernation; +bool suspend_locked;struct mutex release_mutex;atomic_t num_fifo_resources;
@@ -909,6 +911,7 @@ int vmw_fb_init(struct vmw_private *vmw_priv);int vmw_fb_close (struct vmw_private *dev_priv);int vmw_fb_off (struct vmw_private *vmw_priv);int vmw_fb_on (struct vmw_private *vmw_priv); +void vmw_fb_refresh (struct vmw_private *vmw_priv);/** * Kernel modesetting - vmwgfx_kms.c
@@ -945,6 +948,8 @@ int vmw_kms_present(struct vmw_private *dev_priv,int vmw_kms_update_layout_ioctl (struct drm_device *dev,void *data,struct drm_file *file_priv);void vmw_kms_legacy_hotspot_clear (struct vmw_private *dev_priv); +int vmw_kms_suspend (struct drm_device *dev); +int vmw_kms_resume (struct drm_device *dev); int vmw_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +25 -10
@@ -161,10 +161,17 @@ static int vmw_fb_blank(int blank, struct fb_info *info)return 0 ; } -/* -* Dirty code +/** +* vmw_fb_dirty_flush - flush dirty regions to the kms framebuffer +* +* @work: The struct work_struct associated with this task. +* +* This function flushes the dirty regions of the vmalloc framebuffer to the +* kms framebuffer, and if the kms framebuffer is visible, also updated the +* corresponding displays. Note that this function runs even if the kms +* framebuffer is not bound to a crtc and thus not visible, but it's turned +* off during hibernation using the par->dirty.active bool. */ -static void vmw_fb_dirty_flush (struct work_struct *work) { struct vmw_fb_par *par = container_of(work, struct vmw_fb_par,
@@ -852,12 +859,6 @@ int vmw_fb_off(struct vmw_private *vmw_priv)flush_delayed_work (&info->deferred_work);flush_delayed_work (&par->local_work); -mutex_lock (&par->bo_mutex); -drm_modeset_lock_all (vmw_priv->dev); - (void )vmw_fb_kms_detach (par, true, false); -drm_modeset_unlock_all (vmw_priv->dev); -mutex_unlock (&par->bo_mutex); -return 0 ; }
@@ -873,10 +874,24 @@ int vmw_fb_on(struct vmw_private *vmw_priv) info = vmw_priv->fb_info; par = info->par; -vmw_fb_set_par (info);spin_lock_irqsave (&par->dirty.lock, flags); par->dirty.active = true;spin_unlock_irqrestore (&par->dirty.lock, flags);return 0 ; } + +/** +* vmw_fb_refresh - Refresh fb display +* +* @vmw_priv: Pointer to device private +* +* Call into kms to show the fbdev display(s). +*/ +void vmw_fb_refresh (struct vmw_private *vmw_priv) +{ +if (!vmw_priv->fb_info) +return ; + +vmw_fb_set_par (vmw_priv->fb_info); +}
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +48 -0
51 lines not on this page · raw message
Signature · 6 lines
2.14.3 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 6/11 drm/vmwgfx: Get rid of the device-private suspended member
In reply to Thomas HellstromIt was used to early block fbdev dirty processing. Replace it with an unprotected check of the par->dirty.active field. While this might race with the vmw_fb_off() function, we do a protected check later so the race will at worst lead to grabbing and releasing a couple of locks.
--- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 3 --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 2 +- 3 files changed, 1 insertion(+), 5 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +0 -3
@@ -1449,7 +1449,6 @@ static int vmw_pm_freeze(struct device *kdev)DRM_ERROR ("Failed to freeze modesetting.\n" );return ret; } - dev_priv->suspended = true;if (dev_priv->enable_fb)vmw_fb_off (dev_priv);
@@ -1471,7 +1470,6 @@ static int vmw_pm_freeze(struct device *kdev)vmw_kms_resume (dev);if (dev_priv->enable_fb)vmw_fb_on (dev_priv); - dev_priv->suspended = false;vmw_fb_refresh (dev_priv);return -EBUSY ; }
@@ -1512,7 +1510,6 @@ static int vmw_pm_restore(struct device *kdev)if (dev_priv->enable_fb)vmw_fb_on (dev_priv); - dev_priv->suspended = false;vmw_fb_refresh (dev_priv);return 0 ;
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +0 -1
@@ -497,7 +497,6 @@ struct vmw_private {struct vmw_master *active_master;struct vmw_master fbdev_master;struct notifier_block pm_nb; -bool suspended;bool refuse_hibernation;bool suspend_locked;
drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +1 -1
@@ -187,7 +187,7 @@ static void vmw_fb_dirty_flush(struct work_struct *work)struct vmw_dma_buffer *vbo = par->vmw_bo;void *virtual; -if (vmw_priv->suspended) +if (!READ_ONCE (par->dirty.active))return ;mutex_lock (&par->bo_mutex);
Signature · 6 lines
2.14.3 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 7/11 drm/vmwgfx: Use kasprintf
In reply to Thomas HellstromFrom: Himanshu Jha <[email protected]>
Use kasprintf instead of combination of kmalloc and sprintf. Also, remove the local variables used for storing the string length as they are not required now.
--- drivers/gpu/drm/vmwgfx/vmwgfx_msg.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_msg.c +3 -10
@@ -328,7 +328,7 @@ int vmw_host_get_guestinfo(const char *guest_info_param, {struct rpc_channel channel;char *msg, *reply =NULL ; -size_t msg_len, reply_len =0 ; +size_t reply_len =0 ;int ret =0 ;
@@ -338,15 +338,12 @@ int vmw_host_get_guestinfo(const char *guest_info_param,if (!guest_info_param || !length)return -EINVAL ; - msg_len =strlen (guest_info_param) +strlen ("info-get " ) +1 ; - msg =kzalloc (msg_len,GFP_KERNEL ); + msg =kasprintf (GFP_KERNEL ,"info-get %s" , guest_info_param);if (!msg) {DRM_ERROR ("Cannot allocate memory to get %s" , guest_info_param);return -ENOMEM ; } -sprintf (msg,"info-get %s" , guest_info_param); - if (vmw_open_channel(&channel, RPCI_PROTOCOL_NUM) || vmw_send_msg(&channel, msg) || vmw_recv_msg(&channel, (void *) &reply, &reply_len) ||
@@ -388,7 +385,6 @@ int vmw_host_log(const char *log) {struct rpc_channel channel;char *msg; -int msg_len;int ret =0 ;
@@ -398,15 +394,12 @@ int vmw_host_log(const char *log)if (!log)return ret; - msg_len =strlen (log) +strlen ("log " ) +1 ; - msg =kzalloc (msg_len,GFP_KERNEL ); + msg =kasprintf (GFP_KERNEL ,"log %s" , log);if (!msg) {DRM_ERROR ("Cannot allocate memory for log message\n" );return -ENOMEM ; } -sprintf (msg,"log %s" , log); -if (vmw_open_channel (&channel,RPCI_PROTOCOL_NUM ) ||vmw_send_msg (&channel, msg) ||vmw_close_channel (&channel)) {
Signature · 6 lines
2.14.3 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 8/11 drm/vmwgfx: Stricter count of legacy surface device resources
In reply to Thomas HellstromFor legacy surfaces, they were previously registered as device resources when the driver resources were created. Since they are evictable we instead register them as device resources once they are created on the device, just like for guest-backed surfaces. This has implications during hibernation where we can't hibernate with device resources active.
--- drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +3 -5
@@ -345,7 +345,6 @@ static void vmw_hw_surface_destroy(struct vmw_resource *res) dev_priv->used_memory_size -= res->backup_size;mutex_unlock (&dev_priv->cmdbuf_mutex); } -vmw_fifo_resource_dec (dev_priv); }/**
@@ -407,6 +406,8 @@ static int vmw_legacy_srf_create(struct vmw_resource *res)vmw_surface_define_encode (srf, cmd);vmw_fifo_commit (dev_priv, submit_size); +vmw_fifo_resource_inc (dev_priv); +/* * Surface memory usage accounting. */
@@ -558,6 +559,7 @@ static int vmw_legacy_srf_destroy(struct vmw_resource *res)*/ vmw_resource_release_id (res); +vmw_fifo_resource_dec (dev_priv);return 0 ; }
@@ -579,15 +581,11 @@ static int vmw_surface_init(struct vmw_private *dev_priv,struct vmw_resource *res = &srf->res;BUG_ON (!res_free); -if (!dev_priv->has_mob) -vmw_fifo_resource_inc (dev_priv); ret =vmw_resource_init (dev_priv, res, true, res_free, (dev_priv->has_mob) ? &vmw_gb_surface_func : &vmw_legacy_surface_func);if (unlikely (ret !=0 )) { -if (!dev_priv->has_mob) -vmw_fifo_resource_dec (dev_priv);res_free (res);return ret; }
Signature · 6 lines
2.14.3 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 9/11 drm/vmwgfx: Unpin the screen object backup buffer when not used
In reply to Thomas HellstromWe were relying on the pinned screen object backup buffer to be destroyed when not used. But if we hold a copy of the atomic state, like when hibernating, the backup buffer might not be destroyed since it's refcounted by the atomic state. This causes us to hibernate with a buffer pinned in VRAM.
Fix this by only having the buffer pinned when it is actually used by a screen object.
--- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +21 -8
@@ -405,7 +405,11 @@ vmw_sou_primary_plane_cleanup_fb(struct drm_plane *plane, struct drm_plane_state *old_state) {struct vmw_plane_state *vps =vmw_plane_state_to_vps (old_state); +struct drm_crtc *crtc = plane->state->crtc ? + plane->state->crtc : old_state->crtc; +if (vps->dmabuf) +vmw_dmabuf_unpin (vmw_priv (crtc->dev), vps->dmabuf, false);vmw_dmabuf_unreference (&vps->dmabuf); vps->dmabuf_size =0 ;
@@ -443,10 +447,17 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, } size = new_state->crtc_w * new_state->crtc_h *4 ; + dev_priv =vmw_priv (crtc->dev);if (vps->dmabuf) { -if (vps->dmabuf_size == size) -return 0 ; +if (vps->dmabuf_size == size) { +/* +* Note that this might temporarily up the pin-count +* to 2, until cleanup_fb() is called. +*/ +return vmw_dmabuf_pin_in_vram (dev_priv, vps->dmabuf, + true); + }vmw_dmabuf_unreference (&vps->dmabuf); vps->dmabuf_size =0 ;
@@ -456,7 +467,6 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane,if (!vps->dmabuf)return -ENOMEM ; - dev_priv =vmw_priv (crtc->dev);vmw_svga_enable (dev_priv);/* After we have alloced the backing store might not be able to
@@ -467,13 +477,16 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, &vmw_vram_ne_placement, false, &vmw_dmabuf_bo_free);vmw_overlay_resume_all (dev_priv); - -if (ret !=0 ) +if (ret) { vps->dmabuf =NULL ;/* vmw_dmabuf_init frees on error */ -else - vps->dmabuf_size = size; +return ret; + } -return ret; +/* +* TTM already thinks the buffer is pinned, but make sure the +* pin_count is upped. +*/ +return vmw_dmabuf_pin_in_vram (dev_priv, vps->dmabuf, true); }
Signature · 6 lines
2.14.3 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 10/11 drm/vmwgfx: use monotonic event timestamps
In reply to Thomas HellstromFrom: Arnd Bergmann <[email protected]>
DRM_VMW_EVENT_FENCE_SIGNALED (struct drm_vmw_event_fence) and DRM_EVENT_VBLANK (struct drm_event_vblank) pass timestamps in 32-bit seconds/microseconds format.
As of commit c61eef726a78 ("drm: add support for monotonic vblank timestamps"), other DRM drivers use monotonic times for drm_event_vblank, but vmwgfx still uses CLOCK_REALTIME for both events, which suffers from the y2038/y2106 overflow as well as time jumps.
For consistency, this changes vmwgfx to use ktime_get_ts64 as well, which solves those problems and avoids the deprecated do_gettimeofday() function.
This should be transparent to to user space, as long as it doesn't compare the time against the result of gettimeofday().
--- drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +5 -4
@@ -901,11 +901,12 @@ static void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action)spin_lock_irq (&dev->event_lock);if (likely (eaction->tv_sec !=NULL )) { -struct timeval tv; +struct timespec64 ts; -do_gettimeofday (&tv); - *eaction->tv_sec = tv.tv_sec; - *eaction->tv_usec = tv.tv_usec; +ktime_get_ts64 (&ts); +/* monotonic time, so no y2038 overflow */ + *eaction->tv_sec = ts.tv_sec; + *eaction->tv_usec = ts.tv_nsec /NSEC_PER_USEC ; }drm_send_event_locked (dev, eaction->event);
Signature · 6 lines
2.14.3 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 11/11 drm/vmwgfx: Bump version patchlevel and date
In reply to Thomas Hellstrom--- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +2 -2
@@ -43,10 +43,10 @@#include <linux/sync_file.h> #define VMWGFX_DRIVER_NAME "vmwgfx" -#define VMWGFX_DRIVER_DATE "20170612" +#define VMWGFX_DRIVER_DATE "20180322"#define VMWGFX_DRIVER_MAJOR 2#define VMWGFX_DRIVER_MINOR 14 -#define VMWGFX_DRIVER_PATCHLEVEL 0 +#define VMWGFX_DRIVER_PATCHLEVEL 1#define VMWGFX_FILE_PAGE_OFFSET 0x00100000#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)#define VMWGFX_MAX_RELOCATIONS 2048
Signature · 6 lines
2.14.3 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel