aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2012-11-20 07:19:35 -0500
committerDave Airlie <airlied@redhat.com>2012-11-20 16:47:06 -0500
commitc0951b797e7d0f2c6b0df2c0e18185c72d0cf1a1 (patch)
tree5f3bb6a46059469b663f4fedf4aa8a5b0a404819
parentbf6f036848ab2151c2498f11cb7d31a52a95dd5c (diff)
drm/vmwgfx: Refactor resource management
Refactor resource management to make it easy to hook up resources that are backed up by buffers. In particular, resources and their backing buffers can be evicted and rebound, if supported by the device. To avoid query deadlocks, the query code is also modified somewhat. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Brian Paul <brianp@vmware.com> Reviewed-by: Dmitry Torokhov <dtor@vmware.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c7
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c32
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h144
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c898
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c7
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_resource.c1506
6 files changed, 1783 insertions, 811 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
index bd78257cba8b..655d57f188d9 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
@@ -60,7 +60,7 @@ int vmw_dmabuf_to_placement(struct vmw_private *dev_priv,
60 if (unlikely(ret != 0)) 60 if (unlikely(ret != 0))
61 return ret; 61 return ret;
62 62
63 vmw_execbuf_release_pinned_bo(dev_priv, false, 0); 63 vmw_execbuf_release_pinned_bo(dev_priv);
64 64
65 ret = ttm_bo_reserve(bo, interruptible, false, false, 0); 65 ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
66 if (unlikely(ret != 0)) 66 if (unlikely(ret != 0))
@@ -105,7 +105,7 @@ int vmw_dmabuf_to_vram_or_gmr(struct vmw_private *dev_priv,
105 return ret; 105 return ret;
106 106
107 if (pin) 107 if (pin)
108 vmw_execbuf_release_pinned_bo(dev_priv, false, 0); 108 vmw_execbuf_release_pinned_bo(dev_priv);
109 109
110 ret = ttm_bo_reserve(bo, interruptible, false, false, 0); 110 ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
111 if (unlikely(ret != 0)) 111 if (unlikely(ret != 0))
@@ -214,8 +214,7 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *dev_priv,
214 return ret; 214 return ret;
215 215
216 if (pin) 216 if (pin)
217 vmw_execbuf_release_pinned_bo(dev_priv, false, 0); 217 vmw_execbuf_release_pinned_bo(dev_priv);
218
219 ret = ttm_bo_reserve(bo, interruptible, false, false, 0); 218 ret = ttm_bo_reserve(bo, interruptible, false, false, 0);
220 if (unlikely(ret != 0)) 219 if (unlikely(ret != 0))
221 goto err_unlock; 220 goto err_unlock;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 56973cd41735..91581fd5004b 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -432,6 +432,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
432 struct vmw_private *dev_priv; 432 struct vmw_private *dev_priv;
433 int ret; 433 int ret;
434 uint32_t svga_id; 434 uint32_t svga_id;
435 enum vmw_res_type i;
435 436
436 dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); 437 dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
437 if (unlikely(dev_priv == NULL)) { 438 if (unlikely(dev_priv == NULL)) {
@@ -448,15 +449,18 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
448 mutex_init(&dev_priv->cmdbuf_mutex); 449 mutex_init(&dev_priv->cmdbuf_mutex);
449 mutex_init(&dev_priv->release_mutex); 450 mutex_init(&dev_priv->release_mutex);
450 rwlock_init(&dev_priv->resource_lock); 451 rwlock_init(&dev_priv->resource_lock);
451 idr_init(&dev_priv->context_idr); 452
452 idr_init(&dev_priv->surface_idr); 453 for (i = vmw_res_context; i < vmw_res_max; ++i) {
453 idr_init(&dev_priv->stream_idr); 454 idr_init(&dev_priv->res_idr[i]);
455 INIT_LIST_HEAD(&dev_priv->res_lru[i]);
456 }
457
454 mutex_init(&dev_priv->init_mutex); 458 mutex_init(&dev_priv->init_mutex);
455 init_waitqueue_head(&dev_priv->fence_queue); 459 init_waitqueue_head(&dev_priv->fence_queue);
456 init_waitqueue_head(&dev_priv->fifo_queue); 460 init_waitqueue_head(&dev_priv->fifo_queue);
457 dev_priv->fence_queue_waiters = 0; 461 dev_priv->fence_queue_waiters = 0;
458 atomic_set(&dev_priv->fifo_queue_waiters, 0); 462 atomic_set(&dev_priv->fifo_queue_waiters, 0);
459 INIT_LIST_HEAD(&dev_priv->surface_lru); 463
460 dev_priv->used_memory_size = 0; 464 dev_priv->used_memory_size = 0;
461 465
462 dev_priv->io_start = pci_resource_start(dev->pdev, 0); 466 dev_priv->io_start = pci_resource_start(dev->pdev, 0);
@@ -670,9 +674,9 @@ out_err2:
670out_err1: 674out_err1:
671 vmw_ttm_global_release(dev_priv); 675 vmw_ttm_global_release(dev_priv);
672out_err0: 676out_err0:
673 idr_destroy(&dev_priv->surface_idr); 677 for (i = vmw_res_context; i < vmw_res_max; ++i)
674 idr_destroy(&dev_priv->context_idr); 678 idr_destroy(&dev_priv->res_idr[i]);
675 idr_destroy(&dev_priv->stream_idr); 679
676 kfree(dev_priv); 680 kfree(dev_priv);
677 return ret; 681 return ret;
678} 682}
@@ -680,9 +684,12 @@ out_err0:
680static int vmw_driver_unload(struct drm_device *dev) 684static int vmw_driver_unload(struct drm_device *dev)
681{ 685{
682 struct vmw_private *dev_priv = vmw_priv(dev); 686 struct vmw_private *dev_priv = vmw_priv(dev);
687 enum vmw_res_type i;
683 688
684 unregister_pm_notifier(&dev_priv->pm_nb); 689 unregister_pm_notifier(&dev_priv->pm_nb);
685 690
691 if (dev_priv->ctx.res_ht_initialized)
692 drm_ht_remove(&dev_priv->ctx.res_ht);
686 if (dev_priv->ctx.cmd_bounce) 693 if (dev_priv->ctx.cmd_bounce)
687 vfree(dev_priv->ctx.cmd_bounce); 694 vfree(dev_priv->ctx.cmd_bounce);
688 if (dev_priv->enable_fb) { 695 if (dev_priv->enable_fb) {
@@ -709,9 +716,9 @@ static int vmw_driver_unload(struct drm_device *dev)
709 (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM); 716 (void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM);
710 (void)ttm_bo_device_release(&dev_priv->bdev); 717 (void)ttm_bo_device_release(&dev_priv->bdev);
711 vmw_ttm_global_release(dev_priv); 718 vmw_ttm_global_release(dev_priv);
712 idr_destroy(&dev_priv->surface_idr); 719
713 idr_destroy(&dev_priv->context_idr); 720 for (i = vmw_res_context; i < vmw_res_max; ++i)
714 idr_destroy(&dev_priv->stream_idr); 721 idr_destroy(&dev_priv->res_idr[i]);
715 722
716 kfree(dev_priv); 723 kfree(dev_priv);
717 724
@@ -935,7 +942,7 @@ static void vmw_master_drop(struct drm_device *dev,
935 942
936 vmw_fp->locked_master = drm_master_get(file_priv->master); 943 vmw_fp->locked_master = drm_master_get(file_priv->master);
937 ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile); 944 ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile);
938 vmw_execbuf_release_pinned_bo(dev_priv, false, 0); 945 vmw_execbuf_release_pinned_bo(dev_priv);
939 946
940 if (unlikely((ret != 0))) { 947 if (unlikely((ret != 0))) {
941 DRM_ERROR("Unable to lock TTM at VT switch.\n"); 948 DRM_ERROR("Unable to lock TTM at VT switch.\n");
@@ -987,7 +994,8 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
987 * This empties VRAM and unbinds all GMR bindings. 994 * This empties VRAM and unbinds all GMR bindings.
988 * Buffer contents is moved to swappable memory. 995 * Buffer contents is moved to swappable memory.
989 */ 996 */
990 vmw_execbuf_release_pinned_bo(dev_priv, false, 0); 997 vmw_execbuf_release_pinned_bo(dev_priv);
998 vmw_resource_evict_all(dev_priv);
991 ttm_bo_swapout_all(&dev_priv->bdev); 999 ttm_bo_swapout_all(&dev_priv->bdev);
992 1000
993 break; 1001 break;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 7c6f6e3a3c81..34dce9e2b6d2 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -67,31 +67,46 @@ struct vmw_fpriv {
67 67
68struct vmw_dma_buffer { 68struct vmw_dma_buffer {
69 struct ttm_buffer_object base; 69 struct ttm_buffer_object base;
70 struct list_head validate_list; 70 struct list_head res_list;
71 bool gmr_bound;
72 uint32_t cur_validate_node;
73 bool on_validate_list;
74}; 71};
75 72
73/**
74 * struct vmw_validate_buffer - Carries validation info about buffers.
75 *
76 * @base: Validation info for TTM.
77 * @hash: Hash entry for quick lookup of the TTM buffer object.
78 *
79 * This structure contains also driver private validation info
80 * on top of the info needed by TTM.
81 */
82struct vmw_validate_buffer {
83 struct ttm_validate_buffer base;
84 struct drm_hash_item hash;
85};
86
87struct vmw_res_func;
76struct vmw_resource { 88struct vmw_resource {
77 struct kref kref; 89 struct kref kref;
78 struct vmw_private *dev_priv; 90 struct vmw_private *dev_priv;
79 struct idr *idr;
80 int id; 91 int id;
81 enum ttm_object_type res_type;
82 bool avail; 92 bool avail;
83 void (*remove_from_lists) (struct vmw_resource *res); 93 unsigned long backup_size;
84 void (*hw_destroy) (struct vmw_resource *res); 94 bool res_dirty; /* Protected by backup buffer reserved */
95 bool backup_dirty; /* Protected by backup buffer reserved */
96 struct vmw_dma_buffer *backup;
97 unsigned long backup_offset;
98 const struct vmw_res_func *func;
99 struct list_head lru_head; /* Protected by the resource lock */
100 struct list_head mob_head; /* Protected by @backup reserved */
85 void (*res_free) (struct vmw_resource *res); 101 void (*res_free) (struct vmw_resource *res);
86 struct list_head validate_head; 102 void (*hw_destroy) (struct vmw_resource *res);
87 struct list_head query_head; /* Protected by the cmdbuf mutex */ 103};
88 /* TODO is a generic snooper needed? */ 104
89#if 0 105enum vmw_res_type {
90 void (*snoop)(struct vmw_resource *res, 106 vmw_res_context,
91 struct ttm_object_file *tfile, 107 vmw_res_surface,
92 SVGA3dCmdHeader *header); 108 vmw_res_stream,
93 void *snoop_priv; 109 vmw_res_max
94#endif
95}; 110};
96 111
97struct vmw_cursor_snooper { 112struct vmw_cursor_snooper {
@@ -105,20 +120,18 @@ struct vmw_surface_offset;
105 120
106struct vmw_surface { 121struct vmw_surface {
107 struct vmw_resource res; 122 struct vmw_resource res;
108 struct list_head lru_head; /* Protected by the resource lock */
109 uint32_t flags; 123 uint32_t flags;
110 uint32_t format; 124 uint32_t format;
111 uint32_t mip_levels[DRM_VMW_MAX_SURFACE_FACES]; 125 uint32_t mip_levels[DRM_VMW_MAX_SURFACE_FACES];
126 struct drm_vmw_size base_size;
112 struct drm_vmw_size *sizes; 127 struct drm_vmw_size *sizes;
113 uint32_t num_sizes; 128 uint32_t num_sizes;
114
115 bool scanout; 129 bool scanout;
116
117 /* TODO so far just a extra pointer */ 130 /* TODO so far just a extra pointer */
118 struct vmw_cursor_snooper snooper; 131 struct vmw_cursor_snooper snooper;
119 struct ttm_buffer_object *backup;
120 struct vmw_surface_offset *offsets; 132 struct vmw_surface_offset *offsets;
121 uint32_t backup_size; 133 SVGA3dTextureFilter autogen_filter;
134 uint32_t multisample_count;
122}; 135};
123 136
124struct vmw_marker_queue { 137struct vmw_marker_queue {
@@ -145,29 +158,46 @@ struct vmw_relocation {
145 uint32_t index; 158 uint32_t index;
146}; 159};
147 160
161/**
162 * struct vmw_res_cache_entry - resource information cache entry
163 *
164 * @valid: Whether the entry is valid, which also implies that the execbuf
165 * code holds a reference to the resource, and it's placed on the
166 * validation list.
167 * @handle: User-space handle of a resource.
168 * @res: Non-ref-counted pointer to the resource.
169 *
170 * Used to avoid frequent repeated user-space handle lookups of the
171 * same resource.
172 */
173struct vmw_res_cache_entry {
174 bool valid;
175 uint32_t handle;
176 struct vmw_resource *res;
177 struct vmw_resource_val_node *node;
178};
179
148struct vmw_sw_context{ 180struct vmw_sw_context{
149 struct ida bo_list; 181 struct drm_open_hash res_ht;
150 uint32_t last_cid; 182 bool res_ht_initialized;
151 bool cid_valid;
152 bool kernel; /**< is the called made from the kernel */ 183 bool kernel; /**< is the called made from the kernel */
153 struct vmw_resource *cur_ctx;
154 uint32_t last_sid;
155 uint32_t sid_translation;
156 bool sid_valid;
157 struct ttm_object_file *tfile; 184 struct ttm_object_file *tfile;
158 struct list_head validate_nodes; 185 struct list_head validate_nodes;
159 struct vmw_relocation relocs[VMWGFX_MAX_RELOCATIONS]; 186 struct vmw_relocation relocs[VMWGFX_MAX_RELOCATIONS];
160 uint32_t cur_reloc; 187 uint32_t cur_reloc;
161 struct ttm_validate_buffer val_bufs[VMWGFX_MAX_VALIDATIONS]; 188 struct vmw_validate_buffer val_bufs[VMWGFX_MAX_VALIDATIONS];
162 uint32_t cur_val_buf; 189 uint32_t cur_val_buf;
163 uint32_t *cmd_bounce; 190 uint32_t *cmd_bounce;
164 uint32_t cmd_bounce_size; 191 uint32_t cmd_bounce_size;
165 struct list_head resource_list; 192 struct list_head resource_list;
166 uint32_t fence_flags; 193 uint32_t fence_flags;
167 struct list_head query_list;
168 struct ttm_buffer_object *cur_query_bo; 194 struct ttm_buffer_object *cur_query_bo;
169 uint32_t cur_query_cid; 195 struct list_head res_relocations;
170 bool query_cid_valid; 196 uint32_t *buf_start;
197 struct vmw_res_cache_entry res_cache[vmw_res_max];
198 struct vmw_resource *last_query_ctx;
199 bool needs_post_query_barrier;
200 struct vmw_resource *error_resource;
171}; 201};
172 202
173struct vmw_legacy_display; 203struct vmw_legacy_display;
@@ -242,10 +272,7 @@ struct vmw_private {
242 */ 272 */
243 273
244 rwlock_t resource_lock; 274 rwlock_t resource_lock;
245 struct idr context_idr; 275 struct idr res_idr[vmw_res_max];
246 struct idr surface_idr;
247 struct idr stream_idr;
248
249 /* 276 /*
250 * Block lastclose from racing with firstopen. 277 * Block lastclose from racing with firstopen.
251 */ 278 */
@@ -320,6 +347,7 @@ struct vmw_private {
320 struct ttm_buffer_object *dummy_query_bo; 347 struct ttm_buffer_object *dummy_query_bo;
321 struct ttm_buffer_object *pinned_bo; 348 struct ttm_buffer_object *pinned_bo;
322 uint32_t query_cid; 349 uint32_t query_cid;
350 uint32_t query_cid_valid;
323 bool dummy_query_bo_pinned; 351 bool dummy_query_bo_pinned;
324 352
325 /* 353 /*
@@ -329,10 +357,15 @@ struct vmw_private {
329 * protected by the cmdbuf mutex for simplicity. 357 * protected by the cmdbuf mutex for simplicity.
330 */ 358 */
331 359
332 struct list_head surface_lru; 360 struct list_head res_lru[vmw_res_max];
333 uint32_t used_memory_size; 361 uint32_t used_memory_size;
334}; 362};
335 363
364static inline struct vmw_surface *vmw_res_to_srf(struct vmw_resource *res)
365{
366 return container_of(res, struct vmw_surface, res);
367}
368
336static inline struct vmw_private *vmw_priv(struct drm_device *dev) 369static inline struct vmw_private *vmw_priv(struct drm_device *dev)
337{ 370{
338 return (struct vmw_private *)dev->dev_private; 371 return (struct vmw_private *)dev->dev_private;
@@ -381,10 +414,16 @@ extern void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id);
381/** 414/**
382 * Resource utilities - vmwgfx_resource.c 415 * Resource utilities - vmwgfx_resource.c
383 */ 416 */
417struct vmw_user_resource_conv;
418extern const struct vmw_user_resource_conv *user_surface_converter;
419extern const struct vmw_user_resource_conv *user_context_converter;
384 420
385extern struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv); 421extern struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv);
386extern void vmw_resource_unreference(struct vmw_resource **p_res); 422extern void vmw_resource_unreference(struct vmw_resource **p_res);
387extern struct vmw_resource *vmw_resource_reference(struct vmw_resource *res); 423extern struct vmw_resource *vmw_resource_reference(struct vmw_resource *res);
424extern int vmw_resource_validate(struct vmw_resource *res);
425extern int vmw_resource_reserve(struct vmw_resource *res, bool no_backup);
426extern bool vmw_resource_needs_backup(const struct vmw_resource *res);
388extern int vmw_context_destroy_ioctl(struct drm_device *dev, void *data, 427extern int vmw_context_destroy_ioctl(struct drm_device *dev, void *data,
389 struct drm_file *file_priv); 428 struct drm_file *file_priv);
390extern int vmw_context_define_ioctl(struct drm_device *dev, void *data, 429extern int vmw_context_define_ioctl(struct drm_device *dev, void *data,
@@ -398,14 +437,13 @@ extern int vmw_user_lookup_handle(struct vmw_private *dev_priv,
398 uint32_t handle, 437 uint32_t handle,
399 struct vmw_surface **out_surf, 438 struct vmw_surface **out_surf,
400 struct vmw_dma_buffer **out_buf); 439 struct vmw_dma_buffer **out_buf);
440extern int vmw_user_resource_lookup_handle(
441 struct vmw_private *dev_priv,
442 struct ttm_object_file *tfile,
443 uint32_t handle,
444 const struct vmw_user_resource_conv *converter,
445 struct vmw_resource **p_res);
401extern void vmw_surface_res_free(struct vmw_resource *res); 446extern void vmw_surface_res_free(struct vmw_resource *res);
402extern int vmw_surface_init(struct vmw_private *dev_priv,
403 struct vmw_surface *srf,
404 void (*res_free) (struct vmw_resource *res));
405extern int vmw_user_surface_lookup_handle(struct vmw_private *dev_priv,
406 struct ttm_object_file *tfile,
407 uint32_t handle,
408 struct vmw_surface **out);
409extern int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data, 447extern int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
410 struct drm_file *file_priv); 448 struct drm_file *file_priv);
411extern int vmw_surface_define_ioctl(struct drm_device *dev, void *data, 449extern int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
@@ -440,7 +478,14 @@ extern int vmw_user_stream_lookup(struct vmw_private *dev_priv,
440 struct ttm_object_file *tfile, 478 struct ttm_object_file *tfile,
441 uint32_t *inout_id, 479 uint32_t *inout_id,
442 struct vmw_resource **out); 480 struct vmw_resource **out);
443extern void vmw_resource_unreserve(struct list_head *list); 481extern void vmw_resource_unreserve(struct vmw_resource *res,
482 struct vmw_dma_buffer *new_backup,
483 unsigned long new_backup_offset);
484extern void vmw_resource_move_notify(struct ttm_buffer_object *bo,
485 struct ttm_mem_reg *mem);
486extern void vmw_fence_single_bo(struct ttm_buffer_object *bo,
487 struct vmw_fence_obj *fence);
488extern void vmw_resource_evict_all(struct vmw_private *dev_priv);
444 489
445/** 490/**
446 * DMA buffer helper routines - vmwgfx_dmabuf.c 491 * DMA buffer helper routines - vmwgfx_dmabuf.c
@@ -538,10 +583,9 @@ extern int vmw_execbuf_process(struct drm_file *file_priv,
538 struct drm_vmw_fence_rep __user 583 struct drm_vmw_fence_rep __user
539 *user_fence_rep, 584 *user_fence_rep,
540 struct vmw_fence_obj **out_fence); 585 struct vmw_fence_obj **out_fence);
541 586extern void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
542extern void 587 struct vmw_fence_obj *fence);
543vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv, 588extern void vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv);
544 bool only_on_cid_match, uint32_t cid);
545 589
546extern int vmw_execbuf_fence_commands(struct drm_file *file_priv, 590extern int vmw_execbuf_fence_commands(struct drm_file *file_priv,
547 struct vmw_private *dev_priv, 591 struct vmw_private *dev_priv,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index e5775a0db495..534c96703c3f 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -30,6 +30,181 @@
30#include <drm/ttm/ttm_bo_api.h> 30#include <drm/ttm/ttm_bo_api.h>
31#include <drm/ttm/ttm_placement.h> 31#include <drm/ttm/ttm_placement.h>
32 32
33#define VMW_RES_HT_ORDER 12
34
35/**
36 * struct vmw_resource_relocation - Relocation info for resources
37 *
38 * @head: List head for the software context's relocation list.
39 * @res: Non-ref-counted pointer to the resource.
40 * @offset: Offset of 4 byte entries into the command buffer where the
41 * id that needs fixup is located.
42 */
43struct vmw_resource_relocation {
44 struct list_head head;
45 const struct vmw_resource *res;
46 unsigned long offset;
47};
48
49/**
50 * struct vmw_resource_val_node - Validation info for resources
51 *
52 * @head: List head for the software context's resource list.
53 * @hash: Hash entry for quick resouce to val_node lookup.
54 * @res: Ref-counted pointer to the resource.
55 * @switch_backup: Boolean whether to switch backup buffer on unreserve.
56 * @new_backup: Refcounted pointer to the new backup buffer.
57 * @new_backup_offset: New backup buffer offset if @new_backup is non-NUll.
58 * @first_usage: Set to true the first time the resource is referenced in
59 * the command stream.
60 * @no_buffer_needed: Resources do not need to allocate buffer backup on
61 * reservation. The command stream will provide one.
62 */
63struct vmw_resource_val_node {
64 struct list_head head;
65 struct drm_hash_item hash;
66 struct vmw_resource *res;
67 struct vmw_dma_buffer *new_backup;
68 unsigned long new_backup_offset;
69 bool first_usage;
70 bool no_buffer_needed;
71};
72
73/**
74 * vmw_resource_unreserve - unreserve resources previously reserved for
75 * command submission.
76 *
77 * @list_head: list of resources to unreserve.
78 * @backoff: Whether command submission failed.
79 */
80static void vmw_resource_list_unreserve(struct list_head *list,
81 bool backoff)
82{
83 struct vmw_resource_val_node *val;
84
85 list_for_each_entry(val, list, head) {
86 struct vmw_resource *res = val->res;
87 struct vmw_dma_buffer *new_backup =
88 backoff ? NULL : val->new_backup;
89
90 vmw_resource_unreserve(res, new_backup,
91 val->new_backup_offset);
92 vmw_dmabuf_unreference(&val->new_backup);
93 }
94}
95
96
97/**
98 * vmw_resource_val_add - Add a resource to the software context's
99 * resource list if it's not already on it.
100 *
101 * @sw_context: Pointer to the software context.
102 * @res: Pointer to the resource.
103 * @p_node On successful return points to a valid pointer to a
104 * struct vmw_resource_val_node, if non-NULL on entry.
105 */
106static int vmw_resource_val_add(struct vmw_sw_context *sw_context,
107 struct vmw_resource *res,
108 struct vmw_resource_val_node **p_node)
109{
110 struct vmw_resource_val_node *node;
111 struct drm_hash_item *hash;
112 int ret;
113
114 if (likely(drm_ht_find_item(&sw_context->res_ht, (unsigned long) res,
115 &hash) == 0)) {
116 node = container_of(hash, struct vmw_resource_val_node, hash);
117 node->first_usage = false;
118 if (unlikely(p_node != NULL))
119 *p_node = node;
120 return 0;
121 }
122
123 node = kzalloc(sizeof(*node), GFP_KERNEL);
124 if (unlikely(node == NULL)) {
125 DRM_ERROR("Failed to allocate a resource validation "
126 "entry.\n");
127 return -ENOMEM;
128 }
129
130 node->hash.key = (unsigned long) res;
131 ret = drm_ht_insert_item(&sw_context->res_ht, &node->hash);
132 if (unlikely(ret != 0)) {
133 DRM_ERROR("Failed to initialize a resource validation "
134 "entry.\n");
135 kfree(node);
136 return ret;
137 }
138 list_add_tail(&node->head, &sw_context->resource_list);
139 node->res = vmw_resource_reference(res);
140 node->first_usage = true;
141
142 if (unlikely(p_node != NULL))
143 *p_node = node;
144
145 return 0;
146}
147
148/**
149 * vmw_resource_relocation_add - Add a relocation to the relocation list
150 *
151 * @list: Pointer to head of relocation list.
152 * @res: The resource.
153 * @offset: Offset into the command buffer currently being parsed where the
154 * id that needs fixup is located. Granularity is 4 bytes.
155 */
156static int vmw_resource_relocation_add(struct list_head *list,
157 const struct vmw_resource *res,
158 unsigned long offset)
159{
160 struct vmw_resource_relocation *rel;
161
162 rel = kmalloc(sizeof(*rel), GFP_KERNEL);
163 if (unlikely(rel == NULL)) {
164 DRM_ERROR("Failed to allocate a resource relocation.\n");
165 return -ENOMEM;
166 }
167
168 rel->res = res;
169 rel->offset = offset;
170 list_add_tail(&rel->head, list);
171
172 return 0;
173}
174
175/**
176 * vmw_resource_relocations_free - Free all relocations on a list
177 *
178 * @list: Pointer to the head of the relocation list.
179 */
180static void vmw_resource_relocations_free(struct list_head *list)
181{
182 struct vmw_resource_relocation *rel, *n;
183
184 list_for_each_entry_safe(rel, n, list, head) {
185 list_del(&rel->head);
186 kfree(rel);
187 }
188}
189
190/**
191 * vmw_resource_relocations_apply - Apply all relocations on a list
192 *
193 * @cb: Pointer to the start of the command buffer bein patch. This need
194 * not be the same buffer as the one being parsed when the relocation
195 * list was built, but the contents must be the same modulo the
196 * resource ids.
197 * @list: Pointer to the head of the relocation list.
198 */
199static void vmw_resource_relocations_apply(uint32_t *cb,
200 struct list_head *list)
201{
202 struct vmw_resource_relocation *rel;
203
204 list_for_each_entry(rel, list, head)
205 cb[rel->offset] = rel->res->id;
206}
207
33static int vmw_cmd_invalid(struct vmw_private *dev_priv, 208static int vmw_cmd_invalid(struct vmw_private *dev_priv,
34 struct vmw_sw_context *sw_context, 209 struct vmw_sw_context *sw_context,
35 SVGA3dCmdHeader *header) 210 SVGA3dCmdHeader *header)
@@ -44,25 +219,11 @@ static int vmw_cmd_ok(struct vmw_private *dev_priv,
44 return 0; 219 return 0;
45} 220}
46 221
47static void vmw_resource_to_validate_list(struct vmw_sw_context *sw_context,
48 struct vmw_resource **p_res)
49{
50 struct vmw_resource *res = *p_res;
51
52 if (list_empty(&res->validate_head)) {
53 list_add_tail(&res->validate_head, &sw_context->resource_list);
54 *p_res = NULL;
55 } else
56 vmw_resource_unreference(p_res);
57}
58
59/** 222/**
60 * vmw_bo_to_validate_list - add a bo to a validate list 223 * vmw_bo_to_validate_list - add a bo to a validate list
61 * 224 *
62 * @sw_context: The software context used for this command submission batch. 225 * @sw_context: The software context used for this command submission batch.
63 * @bo: The buffer object to add. 226 * @bo: The buffer object to add.
64 * @fence_flags: Fence flags to be or'ed with any other fence flags for
65 * this buffer on this submission batch.
66 * @p_val_node: If non-NULL Will be updated with the validate node number 227 * @p_val_node: If non-NULL Will be updated with the validate node number
67 * on return. 228 * on return.
68 * 229 *
@@ -74,21 +235,37 @@ static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context,
74 uint32_t *p_val_node) 235 uint32_t *p_val_node)
75{ 236{
76 uint32_t val_node; 237 uint32_t val_node;
238 struct vmw_validate_buffer *vval_buf;
77 struct ttm_validate_buffer *val_buf; 239 struct ttm_validate_buffer *val_buf;
240 struct drm_hash_item *hash;
241 int ret;
78 242
79 val_node = vmw_dmabuf_validate_node(bo, sw_context->cur_val_buf); 243 if (likely(drm_ht_find_item(&sw_context->res_ht, (unsigned long) bo,
80 244 &hash) == 0)) {
81 if (unlikely(val_node >= VMWGFX_MAX_VALIDATIONS)) { 245 vval_buf = container_of(hash, struct vmw_validate_buffer,
82 DRM_ERROR("Max number of DMA buffers per submission" 246 hash);
83 " exceeded.\n"); 247 val_buf = &vval_buf->base;
84 return -EINVAL; 248 val_node = vval_buf - sw_context->val_bufs;
85 } 249 } else {
86 250 val_node = sw_context->cur_val_buf;
87 val_buf = &sw_context->val_bufs[val_node]; 251 if (unlikely(val_node >= VMWGFX_MAX_VALIDATIONS)) {
88 if (unlikely(val_node == sw_context->cur_val_buf)) { 252 DRM_ERROR("Max number of DMA buffers per submission "
253 "exceeded.\n");
254 return -EINVAL;
255 }
256 vval_buf = &sw_context->val_bufs[val_node];
257 vval_buf->hash.key = (unsigned long) bo;
258 ret = drm_ht_insert_item(&sw_context->res_ht, &vval_buf->hash);
259 if (unlikely(ret != 0)) {
260 DRM_ERROR("Failed to initialize a buffer validation "
261 "entry.\n");
262 return ret;
263 }
264 ++sw_context->cur_val_buf;
265 val_buf = &vval_buf->base;
89 val_buf->bo = ttm_bo_reference(bo); 266 val_buf->bo = ttm_bo_reference(bo);
267 val_buf->reserved = false;
90 list_add_tail(&val_buf->head, &sw_context->validate_nodes); 268 list_add_tail(&val_buf->head, &sw_context->validate_nodes);
91 ++sw_context->cur_val_buf;
92 } 269 }
93 270
94 sw_context->fence_flags |= DRM_VMW_FENCE_FLAG_EXEC; 271 sw_context->fence_flags |= DRM_VMW_FENCE_FLAG_EXEC;
@@ -99,85 +276,174 @@ static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context,
99 return 0; 276 return 0;
100} 277}
101 278
102static int vmw_cmd_cid_check(struct vmw_private *dev_priv, 279/**
103 struct vmw_sw_context *sw_context, 280 * vmw_resources_reserve - Reserve all resources on the sw_context's
104 SVGA3dCmdHeader *header) 281 * resource list.
282 *
283 * @sw_context: Pointer to the software context.
284 *
285 * Note that since vmware's command submission currently is protected by
286 * the cmdbuf mutex, no fancy deadlock avoidance is required for resources,
287 * since only a single thread at once will attempt this.
288 */
289static int vmw_resources_reserve(struct vmw_sw_context *sw_context)
105{ 290{
106 struct vmw_resource *ctx; 291 struct vmw_resource_val_node *val;
107
108 struct vmw_cid_cmd {
109 SVGA3dCmdHeader header;
110 __le32 cid;
111 } *cmd;
112 int ret; 292 int ret;
113 293
114 cmd = container_of(header, struct vmw_cid_cmd, header); 294 list_for_each_entry(val, &sw_context->resource_list, head) {
115 if (likely(sw_context->cid_valid && cmd->cid == sw_context->last_cid)) 295 struct vmw_resource *res = val->res;
116 return 0;
117 296
118 ret = vmw_context_check(dev_priv, sw_context->tfile, cmd->cid, 297 ret = vmw_resource_reserve(res, val->no_buffer_needed);
119 &ctx); 298 if (unlikely(ret != 0))
120 if (unlikely(ret != 0)) { 299 return ret;
121 DRM_ERROR("Could not find or use context %u\n", 300
122 (unsigned) cmd->cid); 301 if (res->backup) {
123 return ret; 302 struct ttm_buffer_object *bo = &res->backup->base;
303
304 ret = vmw_bo_to_validate_list
305 (sw_context, bo, NULL);
306
307 if (unlikely(ret != 0))
308 return ret;
309 }
124 } 310 }
311 return 0;
312}
125 313
126 sw_context->last_cid = cmd->cid; 314/**
127 sw_context->cid_valid = true; 315 * vmw_resources_validate - Validate all resources on the sw_context's
128 sw_context->cur_ctx = ctx; 316 * resource list.
129 vmw_resource_to_validate_list(sw_context, &ctx); 317 *
318 * @sw_context: Pointer to the software context.
319 *
320 * Before this function is called, all resource backup buffers must have
321 * been validated.
322 */
323static int vmw_resources_validate(struct vmw_sw_context *sw_context)
324{
325 struct vmw_resource_val_node *val;
326 int ret;
327
328 list_for_each_entry(val, &sw_context->resource_list, head) {
329 struct vmw_resource *res = val->res;
130 330
331 ret = vmw_resource_validate(res);
332 if (unlikely(ret != 0)) {
333 if (ret != -ERESTARTSYS)
334 DRM_ERROR("Failed to validate resource.\n");
335 return ret;
336 }
337 }
131 return 0; 338 return 0;
132} 339}
133 340
134static int vmw_cmd_sid_check(struct vmw_private *dev_priv, 341/**
342 * vmw_cmd_res_check - Check that a resource is present and if so, put it
343 * on the resource validate list unless it's already there.
344 *
345 * @dev_priv: Pointer to a device private structure.
346 * @sw_context: Pointer to the software context.
347 * @res_type: Resource type.
348 * @converter: User-space visisble type specific information.
349 * @id: Pointer to the location in the command buffer currently being
350 * parsed from where the user-space resource id handle is located.
351 */
352static int vmw_cmd_res_check(struct vmw_private *dev_priv,
135 struct vmw_sw_context *sw_context, 353 struct vmw_sw_context *sw_context,
136 uint32_t *sid) 354 enum vmw_res_type res_type,
355 const struct vmw_user_resource_conv *converter,
356 uint32_t *id,
357 struct vmw_resource_val_node **p_val)
137{ 358{
138 struct vmw_surface *srf; 359 struct vmw_res_cache_entry *rcache =
139 int ret; 360 &sw_context->res_cache[res_type];
140 struct vmw_resource *res; 361 struct vmw_resource *res;
362 struct vmw_resource_val_node *node;
363 int ret;
141 364
142 if (*sid == SVGA3D_INVALID_ID) 365 if (*id == SVGA3D_INVALID_ID)
143 return 0; 366 return 0;
144 367
145 if (likely((sw_context->sid_valid && 368 /*
146 *sid == sw_context->last_sid))) { 369 * Fastpath in case of repeated commands referencing the same
147 *sid = sw_context->sid_translation; 370 * resource
148 return 0; 371 */
149 }
150 372
151 ret = vmw_user_surface_lookup_handle(dev_priv, 373 if (likely(rcache->valid && *id == rcache->handle)) {
152 sw_context->tfile, 374 const struct vmw_resource *res = rcache->res;
153 *sid, &srf); 375
154 if (unlikely(ret != 0)) { 376 rcache->node->first_usage = false;
155 DRM_ERROR("Could ot find or use surface 0x%08x " 377 if (p_val)
156 "address 0x%08lx\n", 378 *p_val = rcache->node;
157 (unsigned int) *sid, 379
158 (unsigned long) sid); 380 return vmw_resource_relocation_add
159 return ret; 381 (&sw_context->res_relocations, res,
382 id - sw_context->buf_start);
160 } 383 }
161 384
162 ret = vmw_surface_validate(dev_priv, srf); 385 ret = vmw_user_resource_lookup_handle(dev_priv,
386 sw_context->tfile,
387 *id,
388 converter,
389 &res);
163 if (unlikely(ret != 0)) { 390 if (unlikely(ret != 0)) {
164 if (ret != -ERESTARTSYS) 391 DRM_ERROR("Could not find or use resource 0x%08x.\n",
165 DRM_ERROR("Could not validate surface.\n"); 392 (unsigned) *id);
166 vmw_surface_unreference(&srf); 393 dump_stack();
167 return ret; 394 return ret;
168 } 395 }
169 396
170 sw_context->last_sid = *sid; 397 rcache->valid = true;
171 sw_context->sid_valid = true; 398 rcache->res = res;
172 sw_context->sid_translation = srf->res.id; 399 rcache->handle = *id;
173 *sid = sw_context->sid_translation;
174 400
175 res = &srf->res; 401 ret = vmw_resource_relocation_add(&sw_context->res_relocations,
176 vmw_resource_to_validate_list(sw_context, &res); 402 res,
403 id - sw_context->buf_start);
404 if (unlikely(ret != 0))
405 goto out_no_reloc;
406
407 ret = vmw_resource_val_add(sw_context, res, &node);
408 if (unlikely(ret != 0))
409 goto out_no_reloc;
177 410
411 rcache->node = node;
412 if (p_val)
413 *p_val = node;
414 vmw_resource_unreference(&res);
178 return 0; 415 return 0;
416
417out_no_reloc:
418 BUG_ON(sw_context->error_resource != NULL);
419 sw_context->error_resource = res;
420
421 return ret;
179} 422}
180 423
424/**
425 * vmw_cmd_cid_check - Check a command header for valid context information.
426 *
427 * @dev_priv: Pointer to a device private structure.
428 * @sw_context: Pointer to the software context.
429 * @header: A command header with an embedded user-space context handle.
430 *
431 * Convenience function: Call vmw_cmd_res_check with the user-space context
432 * handle embedded in @header.
433 */
434static int vmw_cmd_cid_check(struct vmw_private *dev_priv,
435 struct vmw_sw_context *sw_context,
436 SVGA3dCmdHeader *header)
437{
438 struct vmw_cid_cmd {
439 SVGA3dCmdHeader header;
440 __le32 cid;
441 } *cmd;
442
443 cmd = container_of(header, struct vmw_cid_cmd, header);
444 return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
445 user_context_converter, &cmd->cid, NULL);
446}
181 447
182static int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv, 448static int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv,
183 struct vmw_sw_context *sw_context, 449 struct vmw_sw_context *sw_context,
@@ -194,7 +460,9 @@ static int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv,
194 return ret; 460 return ret;
195 461
196 cmd = container_of(header, struct vmw_sid_cmd, header); 462 cmd = container_of(header, struct vmw_sid_cmd, header);
197 ret = vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.target.sid); 463 ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
464 user_surface_converter,
465 &cmd->body.target.sid, NULL);
198 return ret; 466 return ret;
199} 467}
200 468
@@ -209,10 +477,14 @@ static int vmw_cmd_surface_copy_check(struct vmw_private *dev_priv,
209 int ret; 477 int ret;
210 478
211 cmd = container_of(header, struct vmw_sid_cmd, header); 479 cmd = container_of(header, struct vmw_sid_cmd, header);
212 ret = vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.src.sid); 480 ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
481 user_surface_converter,
482 &cmd->body.src.sid, NULL);
213 if (unlikely(ret != 0)) 483 if (unlikely(ret != 0))
214 return ret; 484 return ret;
215 return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.dest.sid); 485 return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
486 user_surface_converter,
487 &cmd->body.dest.sid, NULL);
216} 488}
217 489
218static int vmw_cmd_stretch_blt_check(struct vmw_private *dev_priv, 490static int vmw_cmd_stretch_blt_check(struct vmw_private *dev_priv,
@@ -226,10 +498,14 @@ static int vmw_cmd_stretch_blt_check(struct vmw_private *dev_priv,
226 int ret; 498 int ret;
227 499
228 cmd = container_of(header, struct vmw_sid_cmd, header); 500 cmd = container_of(header, struct vmw_sid_cmd, header);
229 ret = vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.src.sid); 501 ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
502 user_surface_converter,
503 &cmd->body.src.sid, NULL);
230 if (unlikely(ret != 0)) 504 if (unlikely(ret != 0))
231 return ret; 505 return ret;
232 return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.dest.sid); 506 return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
507 user_surface_converter,
508 &cmd->body.dest.sid, NULL);
233} 509}
234 510
235static int vmw_cmd_blt_surf_screen_check(struct vmw_private *dev_priv, 511static int vmw_cmd_blt_surf_screen_check(struct vmw_private *dev_priv,
@@ -248,7 +524,9 @@ static int vmw_cmd_blt_surf_screen_check(struct vmw_private *dev_priv,
248 return -EPERM; 524 return -EPERM;
249 } 525 }
250 526
251 return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.srcImage.sid); 527 return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
528 user_surface_converter,
529 &cmd->body.srcImage.sid, NULL);
252} 530}
253 531
254static int vmw_cmd_present_check(struct vmw_private *dev_priv, 532static int vmw_cmd_present_check(struct vmw_private *dev_priv,
@@ -268,14 +546,15 @@ static int vmw_cmd_present_check(struct vmw_private *dev_priv,
268 return -EPERM; 546 return -EPERM;
269 } 547 }
270 548
271 return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.sid); 549 return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
550 user_surface_converter, &cmd->body.sid,
551 NULL);
272} 552}
273 553
274/** 554/**
275 * vmw_query_bo_switch_prepare - Prepare to switch pinned buffer for queries. 555 * vmw_query_bo_switch_prepare - Prepare to switch pinned buffer for queries.
276 * 556 *
277 * @dev_priv: The device private structure. 557 * @dev_priv: The device private structure.
278 * @cid: The hardware context for the next query.
279 * @new_query_bo: The new buffer holding query results. 558 * @new_query_bo: The new buffer holding query results.
280 * @sw_context: The software context used for this command submission. 559 * @sw_context: The software context used for this command submission.
281 * 560 *
@@ -283,18 +562,18 @@ static int vmw_cmd_present_check(struct vmw_private *dev_priv,
283 * query results, and if another buffer currently is pinned for query 562 * query results, and if another buffer currently is pinned for query
284 * results. If so, the function prepares the state of @sw_context for 563 * results. If so, the function prepares the state of @sw_context for
285 * switching pinned buffers after successful submission of the current 564 * switching pinned buffers after successful submission of the current
286 * command batch. It also checks whether we're using a new query context. 565 * command batch.
287 * In that case, it makes sure we emit a query barrier for the old
288 * context before the current query buffer is fenced.
289 */ 566 */
290static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv, 567static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,
291 uint32_t cid,
292 struct ttm_buffer_object *new_query_bo, 568 struct ttm_buffer_object *new_query_bo,
293 struct vmw_sw_context *sw_context) 569 struct vmw_sw_context *sw_context)
294{ 570{
571 struct vmw_res_cache_entry *ctx_entry =
572 &sw_context->res_cache[vmw_res_context];
295 int ret; 573 int ret;
296 bool add_cid = false; 574
297 uint32_t cid_to_add; 575 BUG_ON(!ctx_entry->valid);
576 sw_context->last_query_ctx = ctx_entry->res;
298 577
299 if (unlikely(new_query_bo != sw_context->cur_query_bo)) { 578 if (unlikely(new_query_bo != sw_context->cur_query_bo)) {
300 579
@@ -304,9 +583,7 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,
304 } 583 }
305 584
306 if (unlikely(sw_context->cur_query_bo != NULL)) { 585 if (unlikely(sw_context->cur_query_bo != NULL)) {
307 BUG_ON(!sw_context->query_cid_valid); 586 sw_context->needs_post_query_barrier = true;
308 add_cid = true;
309 cid_to_add = sw_context->cur_query_cid;
310 ret = vmw_bo_to_validate_list(sw_context, 587 ret = vmw_bo_to_validate_list(sw_context,
311 sw_context->cur_query_bo, 588 sw_context->cur_query_bo,
312 NULL); 589 NULL);
@@ -323,27 +600,6 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,
323 600
324 } 601 }
325 602
326 if (unlikely(cid != sw_context->cur_query_cid &&
327 sw_context->query_cid_valid)) {
328 add_cid = true;
329 cid_to_add = sw_context->cur_query_cid;
330 }
331
332 sw_context->cur_query_cid = cid;
333 sw_context->query_cid_valid = true;
334
335 if (add_cid) {
336 struct vmw_resource *ctx = sw_context->cur_ctx;
337
338 if (list_empty(&ctx->query_head))
339 list_add_tail(&ctx->query_head,
340 &sw_context->query_list);
341 ret = vmw_bo_to_validate_list(sw_context,
342 dev_priv->dummy_query_bo,
343 NULL);
344 if (unlikely(ret != 0))
345 return ret;
346 }
347 return 0; 603 return 0;
348} 604}
349 605
@@ -355,10 +611,9 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,
355 * @sw_context: The software context used for this command submission batch. 611 * @sw_context: The software context used for this command submission batch.
356 * 612 *
357 * This function will check if we're switching query buffers, and will then, 613 * This function will check if we're switching query buffers, and will then,
358 * if no other query waits are issued this command submission batch,
359 * issue a dummy occlusion query wait used as a query barrier. When the fence 614 * issue a dummy occlusion query wait used as a query barrier. When the fence
360 * object following that query wait has signaled, we are sure that all 615 * object following that query wait has signaled, we are sure that all
361 * preseding queries have finished, and the old query buffer can be unpinned. 616 * preceding queries have finished, and the old query buffer can be unpinned.
362 * However, since both the new query buffer and the old one are fenced with 617 * However, since both the new query buffer and the old one are fenced with
363 * that fence, we can do an asynchronus unpin now, and be sure that the 618 * that fence, we can do an asynchronus unpin now, and be sure that the
364 * old query buffer won't be moved until the fence has signaled. 619 * old query buffer won't be moved until the fence has signaled.
@@ -369,20 +624,19 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,
369static void vmw_query_bo_switch_commit(struct vmw_private *dev_priv, 624static void vmw_query_bo_switch_commit(struct vmw_private *dev_priv,
370 struct vmw_sw_context *sw_context) 625 struct vmw_sw_context *sw_context)
371{ 626{
372
373 struct vmw_resource *ctx, *next_ctx;
374 int ret;
375
376 /* 627 /*
377 * The validate list should still hold references to all 628 * The validate list should still hold references to all
378 * contexts here. 629 * contexts here.
379 */ 630 */
380 631
381 list_for_each_entry_safe(ctx, next_ctx, &sw_context->query_list, 632 if (sw_context->needs_post_query_barrier) {
382 query_head) { 633 struct vmw_res_cache_entry *ctx_entry =
383 list_del_init(&ctx->query_head); 634 &sw_context->res_cache[vmw_res_context];
635 struct vmw_resource *ctx;
636 int ret;
384 637
385 BUG_ON(list_empty(&ctx->validate_head)); 638 BUG_ON(!ctx_entry->valid);
639 ctx = ctx_entry->res;
386 640
387 ret = vmw_fifo_emit_dummy_query(dev_priv, ctx->id); 641 ret = vmw_fifo_emit_dummy_query(dev_priv, ctx->id);
388 642
@@ -396,40 +650,46 @@ static void vmw_query_bo_switch_commit(struct vmw_private *dev_priv,
396 ttm_bo_unref(&dev_priv->pinned_bo); 650 ttm_bo_unref(&dev_priv->pinned_bo);
397 } 651 }
398 652
399 vmw_bo_pin(sw_context->cur_query_bo, true); 653 if (!sw_context->needs_post_query_barrier) {
654 vmw_bo_pin(sw_context->cur_query_bo, true);
400 655
401 /* 656 /*
402 * We pin also the dummy_query_bo buffer so that we 657 * We pin also the dummy_query_bo buffer so that we
403 * don't need to validate it when emitting 658 * don't need to validate it when emitting
404 * dummy queries in context destroy paths. 659 * dummy queries in context destroy paths.
405 */ 660 */
406 661
407 vmw_bo_pin(dev_priv->dummy_query_bo, true); 662 vmw_bo_pin(dev_priv->dummy_query_bo, true);
408 dev_priv->dummy_query_bo_pinned = true; 663 dev_priv->dummy_query_bo_pinned = true;
409 664
410 dev_priv->query_cid = sw_context->cur_query_cid; 665 BUG_ON(sw_context->last_query_ctx == NULL);
411 dev_priv->pinned_bo = 666 dev_priv->query_cid = sw_context->last_query_ctx->id;
412 ttm_bo_reference(sw_context->cur_query_bo); 667 dev_priv->query_cid_valid = true;
668 dev_priv->pinned_bo =
669 ttm_bo_reference(sw_context->cur_query_bo);
670 }
413 } 671 }
414} 672}
415 673
416/** 674/**
417 * vmw_query_switch_backoff - clear query barrier list 675 * vmw_translate_guest_pointer - Prepare to translate a user-space buffer
418 * @sw_context: The sw context used for this submission batch. 676 * handle to a valid SVGAGuestPtr
419 * 677 *
420 * This function is used as part of an error path, where a previously 678 * @dev_priv: Pointer to a device private structure.
421 * set up list of query barriers needs to be cleared. 679 * @sw_context: The software context used for this command batch validation.
680 * @ptr: Pointer to the user-space handle to be translated.
681 * @vmw_bo_p: Points to a location that, on successful return will carry
682 * a reference-counted pointer to the DMA buffer identified by the
683 * user-space handle in @id.
422 * 684 *
685 * This function saves information needed to translate a user-space buffer
686 * handle to a valid SVGAGuestPtr. The translation does not take place
687 * immediately, but during a call to vmw_apply_relocations().
688 * This function builds a relocation list and a list of buffers to validate.
689 * The former needs to be freed using either vmw_apply_relocations() or
690 * vmw_free_relocations(). The latter needs to be freed using
691 * vmw_clear_validations.
423 */ 692 */
424static void vmw_query_switch_backoff(struct vmw_sw_context *sw_context)
425{
426 struct list_head *list, *next;
427
428 list_for_each_safe(list, next, &sw_context->query_list) {
429 list_del_init(list);
430 }
431}
432
433static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, 693static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
434 struct vmw_sw_context *sw_context, 694 struct vmw_sw_context *sw_context,
435 SVGAGuestPtr *ptr, 695 SVGAGuestPtr *ptr,
@@ -471,6 +731,37 @@ out_no_reloc:
471 return ret; 731 return ret;
472} 732}
473 733
734/**
735 * vmw_cmd_begin_query - validate a SVGA_3D_CMD_BEGIN_QUERY command.
736 *
737 * @dev_priv: Pointer to a device private struct.
738 * @sw_context: The software context used for this command submission.
739 * @header: Pointer to the command header in the command stream.
740 */
741static int vmw_cmd_begin_query(struct vmw_private *dev_priv,
742 struct vmw_sw_context *sw_context,
743 SVGA3dCmdHeader *header)
744{
745 struct vmw_begin_query_cmd {
746 SVGA3dCmdHeader header;
747 SVGA3dCmdBeginQuery q;
748 } *cmd;
749
750 cmd = container_of(header, struct vmw_begin_query_cmd,
751 header);
752
753 return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
754 user_context_converter, &cmd->q.cid,
755 NULL);
756}
757
758/**
759 * vmw_cmd_end_query - validate a SVGA_3D_CMD_END_QUERY command.
760 *
761 * @dev_priv: Pointer to a device private struct.
762 * @sw_context: The software context used for this command submission.
763 * @header: Pointer to the command header in the command stream.
764 */
474static int vmw_cmd_end_query(struct vmw_private *dev_priv, 765static int vmw_cmd_end_query(struct vmw_private *dev_priv,
475 struct vmw_sw_context *sw_context, 766 struct vmw_sw_context *sw_context,
476 SVGA3dCmdHeader *header) 767 SVGA3dCmdHeader *header)
@@ -493,13 +784,19 @@ static int vmw_cmd_end_query(struct vmw_private *dev_priv,
493 if (unlikely(ret != 0)) 784 if (unlikely(ret != 0))
494 return ret; 785 return ret;
495 786
496 ret = vmw_query_bo_switch_prepare(dev_priv, cmd->q.cid, 787 ret = vmw_query_bo_switch_prepare(dev_priv, &vmw_bo->base, sw_context);
497 &vmw_bo->base, sw_context);
498 788
499 vmw_dmabuf_unreference(&vmw_bo); 789 vmw_dmabuf_unreference(&vmw_bo);
500 return ret; 790 return ret;
501} 791}
502 792
793/*
794 * vmw_cmd_wait_query - validate a SVGA_3D_CMD_WAIT_QUERY command.
795 *
796 * @dev_priv: Pointer to a device private struct.
797 * @sw_context: The software context used for this command submission.
798 * @header: Pointer to the command header in the command stream.
799 */
503static int vmw_cmd_wait_query(struct vmw_private *dev_priv, 800static int vmw_cmd_wait_query(struct vmw_private *dev_priv,
504 struct vmw_sw_context *sw_context, 801 struct vmw_sw_context *sw_context,
505 SVGA3dCmdHeader *header) 802 SVGA3dCmdHeader *header)
@@ -510,7 +807,6 @@ static int vmw_cmd_wait_query(struct vmw_private *dev_priv,
510 SVGA3dCmdWaitForQuery q; 807 SVGA3dCmdWaitForQuery q;
511 } *cmd; 808 } *cmd;
512 int ret; 809 int ret;
513 struct vmw_resource *ctx;
514 810
515 cmd = container_of(header, struct vmw_query_cmd, header); 811 cmd = container_of(header, struct vmw_query_cmd, header);
516 ret = vmw_cmd_cid_check(dev_priv, sw_context, header); 812 ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
@@ -524,16 +820,6 @@ static int vmw_cmd_wait_query(struct vmw_private *dev_priv,
524 return ret; 820 return ret;
525 821
526 vmw_dmabuf_unreference(&vmw_bo); 822 vmw_dmabuf_unreference(&vmw_bo);
527
528 /*
529 * This wait will act as a barrier for previous waits for this
530 * context.
531 */
532
533 ctx = sw_context->cur_ctx;
534 if (!list_empty(&ctx->query_head))
535 list_del_init(&ctx->query_head);
536
537 return 0; 823 return 0;
538} 824}
539 825
@@ -542,14 +828,12 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
542 SVGA3dCmdHeader *header) 828 SVGA3dCmdHeader *header)
543{ 829{
544 struct vmw_dma_buffer *vmw_bo = NULL; 830 struct vmw_dma_buffer *vmw_bo = NULL;
545 struct ttm_buffer_object *bo;
546 struct vmw_surface *srf = NULL; 831 struct vmw_surface *srf = NULL;
547 struct vmw_dma_cmd { 832 struct vmw_dma_cmd {
548 SVGA3dCmdHeader header; 833 SVGA3dCmdHeader header;
549 SVGA3dCmdSurfaceDMA dma; 834 SVGA3dCmdSurfaceDMA dma;
550 } *cmd; 835 } *cmd;
551 int ret; 836 int ret;
552 struct vmw_resource *res;
553 837
554 cmd = container_of(header, struct vmw_dma_cmd, header); 838 cmd = container_of(header, struct vmw_dma_cmd, header);
555 ret = vmw_translate_guest_ptr(dev_priv, sw_context, 839 ret = vmw_translate_guest_ptr(dev_priv, sw_context,
@@ -558,37 +842,20 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
558 if (unlikely(ret != 0)) 842 if (unlikely(ret != 0))
559 return ret; 843 return ret;
560 844
561 bo = &vmw_bo->base; 845 ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
562 ret = vmw_user_surface_lookup_handle(dev_priv, sw_context->tfile, 846 user_surface_converter, &cmd->dma.host.sid,
563 cmd->dma.host.sid, &srf); 847 NULL);
564 if (ret) {
565 DRM_ERROR("could not find surface\n");
566 goto out_no_reloc;
567 }
568
569 ret = vmw_surface_validate(dev_priv, srf);
570 if (unlikely(ret != 0)) { 848 if (unlikely(ret != 0)) {
571 if (ret != -ERESTARTSYS) 849 if (unlikely(ret != -ERESTARTSYS))
572 DRM_ERROR("Culd not validate surface.\n"); 850 DRM_ERROR("could not find surface for DMA.\n");
573 goto out_no_validate; 851 goto out_no_surface;
574 } 852 }
575 853
576 /* 854 srf = vmw_res_to_srf(sw_context->res_cache[vmw_res_surface].res);
577 * Patch command stream with device SID.
578 */
579 cmd->dma.host.sid = srf->res.id;
580 vmw_kms_cursor_snoop(srf, sw_context->tfile, bo, header);
581
582 vmw_dmabuf_unreference(&vmw_bo);
583
584 res = &srf->res;
585 vmw_resource_to_validate_list(sw_context, &res);
586 855
587 return 0; 856 vmw_kms_cursor_snoop(srf, sw_context->tfile, &vmw_bo->base, header);
588 857
589out_no_validate: 858out_no_surface:
590 vmw_surface_unreference(&srf);
591out_no_reloc:
592 vmw_dmabuf_unreference(&vmw_bo); 859 vmw_dmabuf_unreference(&vmw_bo);
593 return ret; 860 return ret;
594} 861}
@@ -621,8 +888,9 @@ static int vmw_cmd_draw(struct vmw_private *dev_priv,
621 } 888 }
622 889
623 for (i = 0; i < cmd->body.numVertexDecls; ++i, ++decl) { 890 for (i = 0; i < cmd->body.numVertexDecls; ++i, ++decl) {
624 ret = vmw_cmd_sid_check(dev_priv, sw_context, 891 ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
625 &decl->array.surfaceId); 892 user_surface_converter,
893 &decl->array.surfaceId, NULL);
626 if (unlikely(ret != 0)) 894 if (unlikely(ret != 0))
627 return ret; 895 return ret;
628 } 896 }
@@ -636,8 +904,9 @@ static int vmw_cmd_draw(struct vmw_private *dev_priv,
636 904
637 range = (SVGA3dPrimitiveRange *) decl; 905 range = (SVGA3dPrimitiveRange *) decl;
638 for (i = 0; i < cmd->body.numRanges; ++i, ++range) { 906 for (i = 0; i < cmd->body.numRanges; ++i, ++range) {
639 ret = vmw_cmd_sid_check(dev_priv, sw_context, 907 ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
640 &range->indexArray.surfaceId); 908 user_surface_converter,
909 &range->indexArray.surfaceId, NULL);
641 if (unlikely(ret != 0)) 910 if (unlikely(ret != 0))
642 return ret; 911 return ret;
643 } 912 }
@@ -668,8 +937,9 @@ static int vmw_cmd_tex_state(struct vmw_private *dev_priv,
668 if (likely(cur_state->name != SVGA3D_TS_BIND_TEXTURE)) 937 if (likely(cur_state->name != SVGA3D_TS_BIND_TEXTURE))
669 continue; 938 continue;
670 939
671 ret = vmw_cmd_sid_check(dev_priv, sw_context, 940 ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
672 &cur_state->value); 941 user_surface_converter,
942 &cur_state->value, NULL);
673 if (unlikely(ret != 0)) 943 if (unlikely(ret != 0))
674 return ret; 944 return ret;
675 } 945 }
@@ -700,6 +970,34 @@ static int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv,
700 return ret; 970 return ret;
701} 971}
702 972
973/**
974 * vmw_cmd_set_shader - Validate an SVGA_3D_CMD_SET_SHADER
975 * command
976 *
977 * @dev_priv: Pointer to a device private struct.
978 * @sw_context: The software context being used for this batch.
979 * @header: Pointer to the command header in the command stream.
980 */
981static int vmw_cmd_set_shader(struct vmw_private *dev_priv,
982 struct vmw_sw_context *sw_context,
983 SVGA3dCmdHeader *header)
984{
985 struct vmw_set_shader_cmd {
986 SVGA3dCmdHeader header;
987 SVGA3dCmdSetShader body;
988 } *cmd;
989 int ret;
990
991 cmd = container_of(header, struct vmw_set_shader_cmd,
992 header);
993
994 ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
995 if (unlikely(ret != 0))
996 return ret;
997
998 return 0;
999}
1000
703static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv, 1001static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv,
704 struct vmw_sw_context *sw_context, 1002 struct vmw_sw_context *sw_context,
705 void *buf, uint32_t *size) 1003 void *buf, uint32_t *size)
@@ -773,16 +1071,20 @@ static vmw_cmd_func vmw_cmd_funcs[SVGA_3D_CMD_MAX] = {
773 VMW_CMD_DEF(SVGA_3D_CMD_PRESENT, &vmw_cmd_present_check), 1071 VMW_CMD_DEF(SVGA_3D_CMD_PRESENT, &vmw_cmd_present_check),
774 VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DEFINE, &vmw_cmd_cid_check), 1072 VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DEFINE, &vmw_cmd_cid_check),
775 VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DESTROY, &vmw_cmd_cid_check), 1073 VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DESTROY, &vmw_cmd_cid_check),
776 VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER, &vmw_cmd_cid_check), 1074 VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER, &vmw_cmd_set_shader),
777 VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER_CONST, &vmw_cmd_cid_check), 1075 VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER_CONST, &vmw_cmd_cid_check),
778 VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_draw), 1076 VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_draw),
779 VMW_CMD_DEF(SVGA_3D_CMD_SETSCISSORRECT, &vmw_cmd_cid_check), 1077 VMW_CMD_DEF(SVGA_3D_CMD_SETSCISSORRECT, &vmw_cmd_cid_check),
780 VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_QUERY, &vmw_cmd_cid_check), 1078 VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_QUERY, &vmw_cmd_begin_query),
781 VMW_CMD_DEF(SVGA_3D_CMD_END_QUERY, &vmw_cmd_end_query), 1079 VMW_CMD_DEF(SVGA_3D_CMD_END_QUERY, &vmw_cmd_end_query),
782 VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_QUERY, &vmw_cmd_wait_query), 1080 VMW_CMD_DEF(SVGA_3D_CMD_WAIT_FOR_QUERY, &vmw_cmd_wait_query),
783 VMW_CMD_DEF(SVGA_3D_CMD_PRESENT_READBACK, &vmw_cmd_ok), 1081 VMW_CMD_DEF(SVGA_3D_CMD_PRESENT_READBACK, &vmw_cmd_ok),
784 VMW_CMD_DEF(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN, 1082 VMW_CMD_DEF(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN,
785 &vmw_cmd_blt_surf_screen_check) 1083 &vmw_cmd_blt_surf_screen_check),
1084 VMW_CMD_DEF(SVGA_3D_CMD_SURFACE_DEFINE_V2, &vmw_cmd_invalid),
1085 VMW_CMD_DEF(SVGA_3D_CMD_GENERATE_MIPMAPS, &vmw_cmd_invalid),
1086 VMW_CMD_DEF(SVGA_3D_CMD_ACTIVATE_SURFACE, &vmw_cmd_invalid),
1087 VMW_CMD_DEF(SVGA_3D_CMD_DEACTIVATE_SURFACE, &vmw_cmd_invalid),
786}; 1088};
787 1089
788static int vmw_cmd_check(struct vmw_private *dev_priv, 1090static int vmw_cmd_check(struct vmw_private *dev_priv,
@@ -829,6 +1131,8 @@ static int vmw_cmd_check_all(struct vmw_private *dev_priv,
829 int32_t cur_size = size; 1131 int32_t cur_size = size;
830 int ret; 1132 int ret;
831 1133
1134 sw_context->buf_start = buf;
1135
832 while (cur_size > 0) { 1136 while (cur_size > 0) {
833 size = cur_size; 1137 size = cur_size;
834 ret = vmw_cmd_check(dev_priv, sw_context, buf, &size); 1138 ret = vmw_cmd_check(dev_priv, sw_context, buf, &size);
@@ -860,43 +1164,63 @@ static void vmw_apply_relocations(struct vmw_sw_context *sw_context)
860 1164
861 for (i = 0; i < sw_context->cur_reloc; ++i) { 1165 for (i = 0; i < sw_context->cur_reloc; ++i) {
862 reloc = &sw_context->relocs[i]; 1166 reloc = &sw_context->relocs[i];
863 validate = &sw_context->val_bufs[reloc->index]; 1167 validate = &sw_context->val_bufs[reloc->index].base;
864 bo = validate->bo; 1168 bo = validate->bo;
865 if (bo->mem.mem_type == TTM_PL_VRAM) { 1169 switch (bo->mem.mem_type) {
1170 case TTM_PL_VRAM:
866 reloc->location->offset += bo->offset; 1171 reloc->location->offset += bo->offset;
867 reloc->location->gmrId = SVGA_GMR_FRAMEBUFFER; 1172 reloc->location->gmrId = SVGA_GMR_FRAMEBUFFER;
868 } else 1173 break;
1174 case VMW_PL_GMR:
869 reloc->location->gmrId = bo->mem.start; 1175 reloc->location->gmrId = bo->mem.start;
1176 break;
1177 default:
1178 BUG();
1179 }
870 } 1180 }
871 vmw_free_relocations(sw_context); 1181 vmw_free_relocations(sw_context);
872} 1182}
873 1183
1184/**
1185 * vmw_resource_list_unrefererence - Free up a resource list and unreference
1186 * all resources referenced by it.
1187 *
1188 * @list: The resource list.
1189 */
1190static void vmw_resource_list_unreference(struct list_head *list)
1191{
1192 struct vmw_resource_val_node *val, *val_next;
1193
1194 /*
1195 * Drop references to resources held during command submission.
1196 */
1197
1198 list_for_each_entry_safe(val, val_next, list, head) {
1199 list_del_init(&val->head);
1200 vmw_resource_unreference(&val->res);
1201 kfree(val);
1202 }
1203}
1204
874static void vmw_clear_validations(struct vmw_sw_context *sw_context) 1205static void vmw_clear_validations(struct vmw_sw_context *sw_context)
875{ 1206{
876 struct ttm_validate_buffer *entry, *next; 1207 struct vmw_validate_buffer *entry, *next;
877 struct vmw_resource *res, *res_next; 1208 struct vmw_resource_val_node *val;
878 1209
879 /* 1210 /*
880 * Drop references to DMA buffers held during command submission. 1211 * Drop references to DMA buffers held during command submission.
881 */ 1212 */
882 list_for_each_entry_safe(entry, next, &sw_context->validate_nodes, 1213 list_for_each_entry_safe(entry, next, &sw_context->validate_nodes,
883 head) { 1214 base.head) {
884 list_del(&entry->head); 1215 list_del(&entry->base.head);
885 vmw_dmabuf_validate_clear(entry->bo); 1216 ttm_bo_unref(&entry->base.bo);
886 ttm_bo_unref(&entry->bo); 1217 (void) drm_ht_remove_item(&sw_context->res_ht, &entry->hash);
887 sw_context->cur_val_buf--; 1218 sw_context->cur_val_buf--;
888 } 1219 }
889 BUG_ON(sw_context->cur_val_buf != 0); 1220 BUG_ON(sw_context->cur_val_buf != 0);
890 1221
891 /* 1222 list_for_each_entry(val, &sw_context->resource_list, head)
892 * Drop references to resources held during command submission. 1223 (void) drm_ht_remove_item(&sw_context->res_ht, &val->hash);
893 */
894 vmw_resource_unreserve(&sw_context->resource_list);
895 list_for_each_entry_safe(res, res_next, &sw_context->resource_list,
896 validate_head) {
897 list_del_init(&res->validate_head);
898 vmw_resource_unreference(&res);
899 }
900} 1224}
901 1225
902static int vmw_validate_single_buffer(struct vmw_private *dev_priv, 1226static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
@@ -939,11 +1263,11 @@ static int vmw_validate_single_buffer(struct vmw_private *dev_priv,
939static int vmw_validate_buffers(struct vmw_private *dev_priv, 1263static int vmw_validate_buffers(struct vmw_private *dev_priv,
940 struct vmw_sw_context *sw_context) 1264 struct vmw_sw_context *sw_context)
941{ 1265{
942 struct ttm_validate_buffer *entry; 1266 struct vmw_validate_buffer *entry;
943 int ret; 1267 int ret;
944 1268
945 list_for_each_entry(entry, &sw_context->validate_nodes, head) { 1269 list_for_each_entry(entry, &sw_context->validate_nodes, base.head) {
946 ret = vmw_validate_single_buffer(dev_priv, entry->bo); 1270 ret = vmw_validate_single_buffer(dev_priv, entry->base.bo);
947 if (unlikely(ret != 0)) 1271 if (unlikely(ret != 0))
948 return ret; 1272 return ret;
949 } 1273 }
@@ -1106,6 +1430,8 @@ int vmw_execbuf_process(struct drm_file *file_priv,
1106{ 1430{
1107 struct vmw_sw_context *sw_context = &dev_priv->ctx; 1431 struct vmw_sw_context *sw_context = &dev_priv->ctx;
1108 struct vmw_fence_obj *fence = NULL; 1432 struct vmw_fence_obj *fence = NULL;
1433 struct vmw_resource *error_resource;
1434 struct list_head resource_list;
1109 uint32_t handle; 1435 uint32_t handle;
1110 void *cmd; 1436 void *cmd;
1111 int ret; 1437 int ret;
@@ -1135,24 +1461,33 @@ int vmw_execbuf_process(struct drm_file *file_priv,
1135 sw_context->kernel = true; 1461 sw_context->kernel = true;
1136 1462
1137 sw_context->tfile = vmw_fpriv(file_priv)->tfile; 1463 sw_context->tfile = vmw_fpriv(file_priv)->tfile;
1138 sw_context->cid_valid = false;
1139 sw_context->sid_valid = false;
1140 sw_context->cur_reloc = 0; 1464 sw_context->cur_reloc = 0;
1141 sw_context->cur_val_buf = 0; 1465 sw_context->cur_val_buf = 0;
1142 sw_context->fence_flags = 0; 1466 sw_context->fence_flags = 0;
1143 INIT_LIST_HEAD(&sw_context->query_list);
1144 INIT_LIST_HEAD(&sw_context->resource_list); 1467 INIT_LIST_HEAD(&sw_context->resource_list);
1145 sw_context->cur_query_bo = dev_priv->pinned_bo; 1468 sw_context->cur_query_bo = dev_priv->pinned_bo;
1146 sw_context->cur_query_cid = dev_priv->query_cid; 1469 sw_context->last_query_ctx = NULL;
1147 sw_context->query_cid_valid = (dev_priv->pinned_bo != NULL); 1470 sw_context->needs_post_query_barrier = false;
1148 1471 memset(sw_context->res_cache, 0, sizeof(sw_context->res_cache));
1149 INIT_LIST_HEAD(&sw_context->validate_nodes); 1472 INIT_LIST_HEAD(&sw_context->validate_nodes);
1473 INIT_LIST_HEAD(&sw_context->res_relocations);
1474 if (!sw_context->res_ht_initialized) {
1475 ret = drm_ht_create(&sw_context->res_ht, VMW_RES_HT_ORDER);
1476 if (unlikely(ret != 0))
1477 goto out_unlock;
1478 sw_context->res_ht_initialized = true;
1479 }
1150 1480
1481 INIT_LIST_HEAD(&resource_list);
1151 ret = vmw_cmd_check_all(dev_priv, sw_context, kernel_commands, 1482 ret = vmw_cmd_check_all(dev_priv, sw_context, kernel_commands,
1152 command_size); 1483 command_size);
1153 if (unlikely(ret != 0)) 1484 if (unlikely(ret != 0))
1154 goto out_err; 1485 goto out_err;
1155 1486
1487 ret = vmw_resources_reserve(sw_context);
1488 if (unlikely(ret != 0))
1489 goto out_err;
1490
1156 ret = ttm_eu_reserve_buffers(&sw_context->validate_nodes); 1491 ret = ttm_eu_reserve_buffers(&sw_context->validate_nodes);
1157 if (unlikely(ret != 0)) 1492 if (unlikely(ret != 0))
1158 goto out_err; 1493 goto out_err;
@@ -1161,24 +1496,31 @@ int vmw_execbuf_process(struct drm_file *file_priv,
1161 if (unlikely(ret != 0)) 1496 if (unlikely(ret != 0))
1162 goto out_err; 1497 goto out_err;
1163 1498
1164 vmw_apply_relocations(sw_context); 1499 ret = vmw_resources_validate(sw_context);
1500 if (unlikely(ret != 0))
1501 goto out_err;
1165 1502
1166 if (throttle_us) { 1503 if (throttle_us) {
1167 ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.marker_queue, 1504 ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.marker_queue,
1168 throttle_us); 1505 throttle_us);
1169 1506
1170 if (unlikely(ret != 0)) 1507 if (unlikely(ret != 0))
1171 goto out_throttle; 1508 goto out_err;
1172 } 1509 }
1173 1510
1174 cmd = vmw_fifo_reserve(dev_priv, command_size); 1511 cmd = vmw_fifo_reserve(dev_priv, command_size);
1175 if (unlikely(cmd == NULL)) { 1512 if (unlikely(cmd == NULL)) {
1176 DRM_ERROR("Failed reserving fifo space for commands.\n"); 1513 DRM_ERROR("Failed reserving fifo space for commands.\n");
1177 ret = -ENOMEM; 1514 ret = -ENOMEM;
1178 goto out_throttle; 1515 goto out_err;
1179 } 1516 }
1180 1517
1518 vmw_apply_relocations(sw_context);
1181 memcpy(cmd, kernel_commands, command_size); 1519 memcpy(cmd, kernel_commands, command_size);
1520
1521 vmw_resource_relocations_apply(cmd, &sw_context->res_relocations);
1522 vmw_resource_relocations_free(&sw_context->res_relocations);
1523
1182 vmw_fifo_commit(dev_priv, command_size); 1524 vmw_fifo_commit(dev_priv, command_size);
1183 1525
1184 vmw_query_bo_switch_commit(dev_priv, sw_context); 1526 vmw_query_bo_switch_commit(dev_priv, sw_context);
@@ -1194,9 +1536,14 @@ int vmw_execbuf_process(struct drm_file *file_priv,
1194 if (ret != 0) 1536 if (ret != 0)
1195 DRM_ERROR("Fence submission error. Syncing.\n"); 1537 DRM_ERROR("Fence submission error. Syncing.\n");
1196 1538
1539 vmw_resource_list_unreserve(&sw_context->resource_list, false);
1197 ttm_eu_fence_buffer_objects(&sw_context->validate_nodes, 1540 ttm_eu_fence_buffer_objects(&sw_context->validate_nodes,
1198 (void *) fence); 1541 (void *) fence);
1199 1542
1543 if (unlikely(dev_priv->pinned_bo != NULL &&
1544 !dev_priv->query_cid_valid))
1545 __vmw_execbuf_release_pinned_bo(dev_priv, fence);
1546
1200 vmw_clear_validations(sw_context); 1547 vmw_clear_validations(sw_context);
1201 vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret, 1548 vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret,
1202 user_fence_rep, fence, handle); 1549 user_fence_rep, fence, handle);
@@ -1209,17 +1556,40 @@ int vmw_execbuf_process(struct drm_file *file_priv,
1209 vmw_fence_obj_unreference(&fence); 1556 vmw_fence_obj_unreference(&fence);
1210 } 1557 }
1211 1558
1559 list_splice_init(&sw_context->resource_list, &resource_list);
1212 mutex_unlock(&dev_priv->cmdbuf_mutex); 1560 mutex_unlock(&dev_priv->cmdbuf_mutex);
1561
1562 /*
1563 * Unreference resources outside of the cmdbuf_mutex to
1564 * avoid deadlocks in resource destruction paths.
1565 */
1566 vmw_resource_list_unreference(&resource_list);
1567
1213 return 0; 1568 return 0;
1214 1569
1215out_err: 1570out_err:
1571 vmw_resource_relocations_free(&sw_context->res_relocations);
1216 vmw_free_relocations(sw_context); 1572 vmw_free_relocations(sw_context);
1217out_throttle:
1218 vmw_query_switch_backoff(sw_context);
1219 ttm_eu_backoff_reservation(&sw_context->validate_nodes); 1573 ttm_eu_backoff_reservation(&sw_context->validate_nodes);
1574 vmw_resource_list_unreserve(&sw_context->resource_list, true);
1220 vmw_clear_validations(sw_context); 1575 vmw_clear_validations(sw_context);
1576 if (unlikely(dev_priv->pinned_bo != NULL &&
1577 !dev_priv->query_cid_valid))
1578 __vmw_execbuf_release_pinned_bo(dev_priv, NULL);
1221out_unlock: 1579out_unlock:
1580 list_splice_init(&sw_context->resource_list, &resource_list);
1581 error_resource = sw_context->error_resource;
1582 sw_context->error_resource = NULL;
1222 mutex_unlock(&dev_priv->cmdbuf_mutex); 1583 mutex_unlock(&dev_priv->cmdbuf_mutex);
1584
1585 /*
1586 * Unreference resources outside of the cmdbuf_mutex to
1587 * avoid deadlocks in resource destruction paths.
1588 */
1589 vmw_resource_list_unreference(&resource_list);
1590 if (unlikely(error_resource != NULL))
1591 vmw_resource_unreference(&error_resource);
1592
1223 return ret; 1593 return ret;
1224} 1594}
1225 1595
@@ -1244,13 +1614,13 @@ static void vmw_execbuf_unpin_panic(struct vmw_private *dev_priv)
1244 1614
1245 1615
1246/** 1616/**
1247 * vmw_execbuf_release_pinned_bo - Flush queries and unpin the pinned 1617 * __vmw_execbuf_release_pinned_bo - Flush queries and unpin the pinned
1248 * query bo. 1618 * query bo.
1249 * 1619 *
1250 * @dev_priv: The device private structure. 1620 * @dev_priv: The device private structure.
1251 * @only_on_cid_match: Only flush and unpin if the current active query cid 1621 * @fence: If non-NULL should point to a struct vmw_fence_obj issued
1252 * matches @cid. 1622 * _after_ a query barrier that flushes all queries touching the current
1253 * @cid: Optional context id to match. 1623 * buffer pointed to by @dev_priv->pinned_bo
1254 * 1624 *
1255 * This function should be used to unpin the pinned query bo, or 1625 * This function should be used to unpin the pinned query bo, or
1256 * as a query barrier when we need to make sure that all queries have 1626 * as a query barrier when we need to make sure that all queries have
@@ -1263,23 +1633,21 @@ static void vmw_execbuf_unpin_panic(struct vmw_private *dev_priv)
1263 * 1633 *
1264 * The function will synchronize on the previous query barrier, and will 1634 * The function will synchronize on the previous query barrier, and will
1265 * thus not finish until that barrier has executed. 1635 * thus not finish until that barrier has executed.
1636 *
1637 * the @dev_priv->cmdbuf_mutex needs to be held by the current thread
1638 * before calling this function.
1266 */ 1639 */
1267void vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv, 1640void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
1268 bool only_on_cid_match, uint32_t cid) 1641 struct vmw_fence_obj *fence)
1269{ 1642{
1270 int ret = 0; 1643 int ret = 0;
1271 struct list_head validate_list; 1644 struct list_head validate_list;
1272 struct ttm_validate_buffer pinned_val, query_val; 1645 struct ttm_validate_buffer pinned_val, query_val;
1273 struct vmw_fence_obj *fence; 1646 struct vmw_fence_obj *lfence = NULL;
1274
1275 mutex_lock(&dev_priv->cmdbuf_mutex);
1276 1647
1277 if (dev_priv->pinned_bo == NULL) 1648 if (dev_priv->pinned_bo == NULL)
1278 goto out_unlock; 1649 goto out_unlock;
1279 1650
1280 if (only_on_cid_match && cid != dev_priv->query_cid)
1281 goto out_unlock;
1282
1283 INIT_LIST_HEAD(&validate_list); 1651 INIT_LIST_HEAD(&validate_list);
1284 1652
1285 pinned_val.bo = ttm_bo_reference(dev_priv->pinned_bo); 1653 pinned_val.bo = ttm_bo_reference(dev_priv->pinned_bo);
@@ -1297,25 +1665,34 @@ void vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
1297 goto out_no_reserve; 1665 goto out_no_reserve;
1298 } 1666 }
1299 1667
1300 ret = vmw_fifo_emit_dummy_query(dev_priv, dev_priv->query_cid); 1668 if (dev_priv->query_cid_valid) {
1301 if (unlikely(ret != 0)) { 1669 BUG_ON(fence != NULL);
1302 vmw_execbuf_unpin_panic(dev_priv); 1670 ret = vmw_fifo_emit_dummy_query(dev_priv, dev_priv->query_cid);
1303 goto out_no_emit; 1671 if (unlikely(ret != 0)) {
1672 vmw_execbuf_unpin_panic(dev_priv);
1673 goto out_no_emit;
1674 }
1675 dev_priv->query_cid_valid = false;
1304 } 1676 }
1305 1677
1306 vmw_bo_pin(dev_priv->pinned_bo, false); 1678 vmw_bo_pin(dev_priv->pinned_bo, false);
1307 vmw_bo_pin(dev_priv->dummy_query_bo, false); 1679 vmw_bo_pin(dev_priv->dummy_query_bo, false);
1308 dev_priv->dummy_query_bo_pinned = false; 1680 dev_priv->dummy_query_bo_pinned = false;
1309 1681
1310 (void) vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL); 1682 if (fence == NULL) {
1683 (void) vmw_execbuf_fence_commands(NULL, dev_priv, &lfence,
1684 NULL);
1685 fence = lfence;
1686 }
1311 ttm_eu_fence_buffer_objects(&validate_list, (void *) fence); 1687 ttm_eu_fence_buffer_objects(&validate_list, (void *) fence);
1688 if (lfence != NULL)
1689 vmw_fence_obj_unreference(&lfence);
1312 1690
1313 ttm_bo_unref(&query_val.bo); 1691 ttm_bo_unref(&query_val.bo);
1314 ttm_bo_unref(&pinned_val.bo); 1692 ttm_bo_unref(&pinned_val.bo);
1315 ttm_bo_unref(&dev_priv->pinned_bo); 1693 ttm_bo_unref(&dev_priv->pinned_bo);
1316 1694
1317out_unlock: 1695out_unlock:
1318 mutex_unlock(&dev_priv->cmdbuf_mutex);
1319 return; 1696 return;
1320 1697
1321out_no_emit: 1698out_no_emit:
@@ -1324,6 +1701,31 @@ out_no_reserve:
1324 ttm_bo_unref(&query_val.bo); 1701 ttm_bo_unref(&query_val.bo);
1325 ttm_bo_unref(&pinned_val.bo); 1702 ttm_bo_unref(&pinned_val.bo);
1326 ttm_bo_unref(&dev_priv->pinned_bo); 1703 ttm_bo_unref(&dev_priv->pinned_bo);
1704}
1705
1706/**
1707 * vmw_execbuf_release_pinned_bo - Flush queries and unpin the pinned
1708 * query bo.
1709 *
1710 * @dev_priv: The device private structure.
1711 *
1712 * This function should be used to unpin the pinned query bo, or
1713 * as a query barrier when we need to make sure that all queries have
1714 * finished before the next fifo command. (For example on hardware
1715 * context destructions where the hardware may otherwise leak unfinished
1716 * queries).
1717 *
1718 * This function does not return any failure codes, but make attempts
1719 * to do safe unpinning in case of errors.
1720 *
1721 * The function will synchronize on the previous query barrier, and will
1722 * thus not finish until that barrier has executed.
1723 */
1724void vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv)
1725{
1726 mutex_lock(&dev_priv->cmdbuf_mutex);
1727 if (dev_priv->query_cid_valid)
1728 __vmw_execbuf_release_pinned_bo(dev_priv, NULL);
1327 mutex_unlock(&dev_priv->cmdbuf_mutex); 1729 mutex_unlock(&dev_priv->cmdbuf_mutex);
1328} 1730}
1329 1731
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
index b07ca2e4d04b..2f7c08ebf568 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
@@ -131,6 +131,7 @@ int vmw_present_ioctl(struct drm_device *dev, void *data,
131 struct drm_vmw_rect *clips = NULL; 131 struct drm_vmw_rect *clips = NULL;
132 struct drm_mode_object *obj; 132 struct drm_mode_object *obj;
133 struct vmw_framebuffer *vfb; 133 struct vmw_framebuffer *vfb;
134 struct vmw_resource *res;
134 uint32_t num_clips; 135 uint32_t num_clips;
135 int ret; 136 int ret;
136 137
@@ -178,11 +179,13 @@ int vmw_present_ioctl(struct drm_device *dev, void *data,
178 if (unlikely(ret != 0)) 179 if (unlikely(ret != 0))
179 goto out_no_ttm_lock; 180 goto out_no_ttm_lock;
180 181
181 ret = vmw_user_surface_lookup_handle(dev_priv, tfile, arg->sid, 182 ret = vmw_user_resource_lookup_handle(dev_priv, tfile, arg->sid,
182 &surface); 183 user_surface_converter,
184 &res);
183 if (ret) 185 if (ret)
184 goto out_no_surface; 186 goto out_no_surface;
185 187
188 surface = vmw_res_to_srf(res);
186 ret = vmw_kms_present(dev_priv, file_priv, 189 ret = vmw_kms_present(dev_priv, file_priv,
187 vfb, surface, arg->sid, 190 vfb, surface, arg->sid,
188 arg->dest_x, arg->dest_y, 191 arg->dest_x, arg->dest_y,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index 292c988c54ea..44ac46bb5629 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -31,15 +31,47 @@
31#include <drm/ttm/ttm_placement.h> 31#include <drm/ttm/ttm_placement.h>
32#include <drm/drmP.h> 32#include <drm/drmP.h>
33 33
34struct vmw_user_context { 34/**
35 struct ttm_base_object base; 35 * struct vmw_user_resource_conv - Identify a derived user-exported resource
36 struct vmw_resource res; 36 * type and provide a function to convert its ttm_base_object pointer to
37 * a struct vmw_resource
38 */
39struct vmw_user_resource_conv {
40 enum ttm_object_type object_type;
41 struct vmw_resource *(*base_obj_to_res)(struct ttm_base_object *base);
42 void (*res_free) (struct vmw_resource *res);
37}; 43};
38 44
39struct vmw_user_surface { 45/**
40 struct ttm_base_object base; 46 * struct vmw_res_func - members and functions common for a resource type
41 struct vmw_surface srf; 47 *
42 uint32_t size; 48 * @res_type: Enum that identifies the lru list to use for eviction.
49 * @needs_backup: Whether the resource is guest-backed and needs
50 * persistent buffer storage.
51 * @type_name: String that identifies the resource type.
52 * @backup_placement: TTM placement for backup buffers.
53 * @may_evict Whether the resource may be evicted.
54 * @create: Create a hardware resource.
55 * @destroy: Destroy a hardware resource.
56 * @bind: Bind a hardware resource to persistent buffer storage.
57 * @unbind: Unbind a hardware resource from persistent
58 * buffer storage.
59 */
60
61struct vmw_res_func {
62 enum vmw_res_type res_type;
63 bool needs_backup;
64 const char *type_name;
65 struct ttm_placement *backup_placement;
66 bool may_evict;
67
68 int (*create) (struct vmw_resource *res);
69 int (*destroy) (struct vmw_resource *res);
70 int (*bind) (struct vmw_resource *res,
71 struct ttm_validate_buffer *val_buf);
72 int (*unbind) (struct vmw_resource *res,
73 bool readback,
74 struct ttm_validate_buffer *val_buf);
43}; 75};
44 76
45struct vmw_user_dma_buffer { 77struct vmw_user_dma_buffer {
@@ -62,16 +94,118 @@ struct vmw_user_stream {
62 struct vmw_stream stream; 94 struct vmw_stream stream;
63}; 95};
64 96
97
98static uint64_t vmw_user_stream_size;
99
100static const struct vmw_res_func vmw_stream_func = {
101 .res_type = vmw_res_stream,
102 .needs_backup = false,
103 .may_evict = false,
104 .type_name = "video streams",
105 .backup_placement = NULL,
106 .create = NULL,
107 .destroy = NULL,
108 .bind = NULL,
109 .unbind = NULL
110};
111
112struct vmw_user_context {
113 struct ttm_base_object base;
114 struct vmw_resource res;
115};
116
117static void vmw_user_context_free(struct vmw_resource *res);
118static struct vmw_resource *
119vmw_user_context_base_to_res(struct ttm_base_object *base);
120
121static uint64_t vmw_user_context_size;
122
123static const struct vmw_user_resource_conv user_context_conv = {
124 .object_type = VMW_RES_CONTEXT,
125 .base_obj_to_res = vmw_user_context_base_to_res,
126 .res_free = vmw_user_context_free
127};
128
129const struct vmw_user_resource_conv *user_context_converter =
130 &user_context_conv;
131
132
133static const struct vmw_res_func vmw_legacy_context_func = {
134 .res_type = vmw_res_context,
135 .needs_backup = false,
136 .may_evict = false,
137 .type_name = "legacy contexts",
138 .backup_placement = NULL,
139 .create = NULL,
140 .destroy = NULL,
141 .bind = NULL,
142 .unbind = NULL
143};
144
145
146/**
147 * struct vmw_user_surface - User-space visible surface resource
148 *
149 * @base: The TTM base object handling user-space visibility.
150 * @srf: The surface metadata.
151 * @size: TTM accounting size for the surface.
152 */
153struct vmw_user_surface {
154 struct ttm_base_object base;
155 struct vmw_surface srf;
156 uint32_t size;
157 uint32_t backup_handle;
158};
159
160/**
161 * struct vmw_surface_offset - Backing store mip level offset info
162 *
163 * @face: Surface face.
164 * @mip: Mip level.
165 * @bo_offset: Offset into backing store of this mip level.
166 *
167 */
65struct vmw_surface_offset { 168struct vmw_surface_offset {
66 uint32_t face; 169 uint32_t face;
67 uint32_t mip; 170 uint32_t mip;
68 uint32_t bo_offset; 171 uint32_t bo_offset;
69}; 172};
70 173
174static void vmw_user_surface_free(struct vmw_resource *res);
175static struct vmw_resource *
176vmw_user_surface_base_to_res(struct ttm_base_object *base);
177static int vmw_legacy_srf_bind(struct vmw_resource *res,
178 struct ttm_validate_buffer *val_buf);
179static int vmw_legacy_srf_unbind(struct vmw_resource *res,
180 bool readback,
181 struct ttm_validate_buffer *val_buf);
182static int vmw_legacy_srf_create(struct vmw_resource *res);
183static int vmw_legacy_srf_destroy(struct vmw_resource *res);
184
185static const struct vmw_user_resource_conv user_surface_conv = {
186 .object_type = VMW_RES_SURFACE,
187 .base_obj_to_res = vmw_user_surface_base_to_res,
188 .res_free = vmw_user_surface_free
189};
190
191const struct vmw_user_resource_conv *user_surface_converter =
192 &user_surface_conv;
193
71 194
72static uint64_t vmw_user_context_size;
73static uint64_t vmw_user_surface_size; 195static uint64_t vmw_user_surface_size;
74static uint64_t vmw_user_stream_size; 196
197static const struct vmw_res_func vmw_legacy_surface_func = {
198 .res_type = vmw_res_surface,
199 .needs_backup = false,
200 .may_evict = true,
201 .type_name = "legacy surfaces",
202 .backup_placement = &vmw_srf_placement,
203 .create = &vmw_legacy_srf_create,
204 .destroy = &vmw_legacy_srf_destroy,
205 .bind = &vmw_legacy_srf_bind,
206 .unbind = &vmw_legacy_srf_unbind
207};
208
75 209
76static inline struct vmw_dma_buffer * 210static inline struct vmw_dma_buffer *
77vmw_dma_buffer(struct ttm_buffer_object *bo) 211vmw_dma_buffer(struct ttm_buffer_object *bo)
@@ -103,10 +237,11 @@ struct vmw_resource *vmw_resource_reference(struct vmw_resource *res)
103static void vmw_resource_release_id(struct vmw_resource *res) 237static void vmw_resource_release_id(struct vmw_resource *res)
104{ 238{
105 struct vmw_private *dev_priv = res->dev_priv; 239 struct vmw_private *dev_priv = res->dev_priv;
240 struct idr *idr = &dev_priv->res_idr[res->func->res_type];
106 241
107 write_lock(&dev_priv->resource_lock); 242 write_lock(&dev_priv->resource_lock);
108 if (res->id != -1) 243 if (res->id != -1)
109 idr_remove(res->idr, res->id); 244 idr_remove(idr, res->id);
110 res->id = -1; 245 res->id = -1;
111 write_unlock(&dev_priv->resource_lock); 246 write_unlock(&dev_priv->resource_lock);
112} 247}
@@ -116,17 +251,33 @@ static void vmw_resource_release(struct kref *kref)
116 struct vmw_resource *res = 251 struct vmw_resource *res =
117 container_of(kref, struct vmw_resource, kref); 252 container_of(kref, struct vmw_resource, kref);
118 struct vmw_private *dev_priv = res->dev_priv; 253 struct vmw_private *dev_priv = res->dev_priv;
119 int id = res->id; 254 int id;
120 struct idr *idr = res->idr; 255 struct idr *idr = &dev_priv->res_idr[res->func->res_type];
121 256
122 res->avail = false; 257 res->avail = false;
123 if (res->remove_from_lists != NULL) 258 list_del_init(&res->lru_head);
124 res->remove_from_lists(res);
125 write_unlock(&dev_priv->resource_lock); 259 write_unlock(&dev_priv->resource_lock);
260 if (res->backup) {
261 struct ttm_buffer_object *bo = &res->backup->base;
262
263 ttm_bo_reserve(bo, false, false, false, 0);
264 if (!list_empty(&res->mob_head) &&
265 res->func->unbind != NULL) {
266 struct ttm_validate_buffer val_buf;
267
268 val_buf.bo = bo;
269 res->func->unbind(res, false, &val_buf);
270 }
271 res->backup_dirty = false;
272 list_del_init(&res->mob_head);
273 ttm_bo_unreserve(bo);
274 vmw_dmabuf_unreference(&res->backup);
275 }
126 276
127 if (likely(res->hw_destroy != NULL)) 277 if (likely(res->hw_destroy != NULL))
128 res->hw_destroy(res); 278 res->hw_destroy(res);
129 279
280 id = res->id;
130 if (res->res_free != NULL) 281 if (res->res_free != NULL)
131 res->res_free(res); 282 res->res_free(res);
132 else 283 else
@@ -153,25 +304,25 @@ void vmw_resource_unreference(struct vmw_resource **p_res)
153/** 304/**
154 * vmw_resource_alloc_id - release a resource id to the id manager. 305 * vmw_resource_alloc_id - release a resource id to the id manager.
155 * 306 *
156 * @dev_priv: Pointer to the device private structure.
157 * @res: Pointer to the resource. 307 * @res: Pointer to the resource.
158 * 308 *
159 * Allocate the lowest free resource from the resource manager, and set 309 * Allocate the lowest free resource from the resource manager, and set
160 * @res->id to that id. Returns 0 on success and -ENOMEM on failure. 310 * @res->id to that id. Returns 0 on success and -ENOMEM on failure.
161 */ 311 */
162static int vmw_resource_alloc_id(struct vmw_private *dev_priv, 312static int vmw_resource_alloc_id(struct vmw_resource *res)
163 struct vmw_resource *res)
164{ 313{
314 struct vmw_private *dev_priv = res->dev_priv;
165 int ret; 315 int ret;
316 struct idr *idr = &dev_priv->res_idr[res->func->res_type];
166 317
167 BUG_ON(res->id != -1); 318 BUG_ON(res->id != -1);
168 319
169 do { 320 do {
170 if (unlikely(idr_pre_get(res->idr, GFP_KERNEL) == 0)) 321 if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0))
171 return -ENOMEM; 322 return -ENOMEM;
172 323
173 write_lock(&dev_priv->resource_lock); 324 write_lock(&dev_priv->resource_lock);
174 ret = idr_get_new_above(res->idr, res, 1, &res->id); 325 ret = idr_get_new_above(idr, res, 1, &res->id);
175 write_unlock(&dev_priv->resource_lock); 326 write_unlock(&dev_priv->resource_lock);
176 327
177 } while (ret == -EAGAIN); 328 } while (ret == -EAGAIN);
@@ -179,31 +330,40 @@ static int vmw_resource_alloc_id(struct vmw_private *dev_priv,
179 return ret; 330 return ret;
180} 331}
181 332
182 333/**
334 * vmw_resource_init - initialize a struct vmw_resource
335 *
336 * @dev_priv: Pointer to a device private struct.
337 * @res: The struct vmw_resource to initialize.
338 * @obj_type: Resource object type.
339 * @delay_id: Boolean whether to defer device id allocation until
340 * the first validation.
341 * @res_free: Resource destructor.
342 * @func: Resource function table.
343 */
183static int vmw_resource_init(struct vmw_private *dev_priv, 344static int vmw_resource_init(struct vmw_private *dev_priv,
184 struct vmw_resource *res, 345 struct vmw_resource *res,
185 struct idr *idr,
186 enum ttm_object_type obj_type,
187 bool delay_id, 346 bool delay_id,
188 void (*res_free) (struct vmw_resource *res), 347 void (*res_free) (struct vmw_resource *res),
189 void (*remove_from_lists) 348 const struct vmw_res_func *func)
190 (struct vmw_resource *res))
191{ 349{
192 kref_init(&res->kref); 350 kref_init(&res->kref);
193 res->hw_destroy = NULL; 351 res->hw_destroy = NULL;
194 res->res_free = res_free; 352 res->res_free = res_free;
195 res->remove_from_lists = remove_from_lists;
196 res->res_type = obj_type;
197 res->idr = idr;
198 res->avail = false; 353 res->avail = false;
199 res->dev_priv = dev_priv; 354 res->dev_priv = dev_priv;
200 INIT_LIST_HEAD(&res->query_head); 355 res->func = func;
201 INIT_LIST_HEAD(&res->validate_head); 356 INIT_LIST_HEAD(&res->lru_head);
357 INIT_LIST_HEAD(&res->mob_head);
202 res->id = -1; 358 res->id = -1;
359 res->backup = NULL;
360 res->backup_offset = 0;
361 res->backup_dirty = false;
362 res->res_dirty = false;
203 if (delay_id) 363 if (delay_id)
204 return 0; 364 return 0;
205 else 365 else
206 return vmw_resource_alloc_id(dev_priv, res); 366 return vmw_resource_alloc_id(res);
207} 367}
208 368
209/** 369/**
@@ -218,7 +378,6 @@ static int vmw_resource_init(struct vmw_private *dev_priv,
218 * Activate basically means that the function vmw_resource_lookup will 378 * Activate basically means that the function vmw_resource_lookup will
219 * find it. 379 * find it.
220 */ 380 */
221
222static void vmw_resource_activate(struct vmw_resource *res, 381static void vmw_resource_activate(struct vmw_resource *res,
223 void (*hw_destroy) (struct vmw_resource *)) 382 void (*hw_destroy) (struct vmw_resource *))
224{ 383{
@@ -263,8 +422,7 @@ static void vmw_hw_context_destroy(struct vmw_resource *res)
263 } *cmd; 422 } *cmd;
264 423
265 424
266 vmw_execbuf_release_pinned_bo(dev_priv, true, res->id); 425 vmw_execbuf_release_pinned_bo(dev_priv);
267
268 cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); 426 cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
269 if (unlikely(cmd == NULL)) { 427 if (unlikely(cmd == NULL)) {
270 DRM_ERROR("Failed reserving FIFO space for surface " 428 DRM_ERROR("Failed reserving FIFO space for surface "
@@ -291,8 +449,8 @@ static int vmw_context_init(struct vmw_private *dev_priv,
291 SVGA3dCmdDefineContext body; 449 SVGA3dCmdDefineContext body;
292 } *cmd; 450 } *cmd;
293 451
294 ret = vmw_resource_init(dev_priv, res, &dev_priv->context_idr, 452 ret = vmw_resource_init(dev_priv, res, false,
295 VMW_RES_CONTEXT, false, res_free, NULL); 453 res_free, &vmw_legacy_context_func);
296 454
297 if (unlikely(ret != 0)) { 455 if (unlikely(ret != 0)) {
298 DRM_ERROR("Failed to allocate a resource id.\n"); 456 DRM_ERROR("Failed to allocate a resource id.\n");
@@ -338,6 +496,7 @@ struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv)
338 return NULL; 496 return NULL;
339 497
340 ret = vmw_context_init(dev_priv, res, NULL); 498 ret = vmw_context_init(dev_priv, res, NULL);
499
341 return (ret == 0) ? res : NULL; 500 return (ret == 0) ? res : NULL;
342} 501}
343 502
@@ -345,6 +504,12 @@ struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv)
345 * User-space context management: 504 * User-space context management:
346 */ 505 */
347 506
507static struct vmw_resource *
508vmw_user_context_base_to_res(struct ttm_base_object *base)
509{
510 return &(container_of(base, struct vmw_user_context, base)->res);
511}
512
348static void vmw_user_context_free(struct vmw_resource *res) 513static void vmw_user_context_free(struct vmw_resource *res)
349{ 514{
350 struct vmw_user_context *ctx = 515 struct vmw_user_context *ctx =
@@ -375,32 +540,10 @@ static void vmw_user_context_base_release(struct ttm_base_object **p_base)
375int vmw_context_destroy_ioctl(struct drm_device *dev, void *data, 540int vmw_context_destroy_ioctl(struct drm_device *dev, void *data,
376 struct drm_file *file_priv) 541 struct drm_file *file_priv)
377{ 542{
378 struct vmw_private *dev_priv = vmw_priv(dev);
379 struct vmw_resource *res;
380 struct vmw_user_context *ctx;
381 struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data; 543 struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data;
382 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 544 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
383 int ret = 0;
384
385 res = vmw_resource_lookup(dev_priv, &dev_priv->context_idr, arg->cid);
386 if (unlikely(res == NULL))
387 return -EINVAL;
388
389 if (res->res_free != &vmw_user_context_free) {
390 ret = -EINVAL;
391 goto out;
392 }
393
394 ctx = container_of(res, struct vmw_user_context, res);
395 if (ctx->base.tfile != tfile && !ctx->base.shareable) {
396 ret = -EPERM;
397 goto out;
398 }
399 545
400 ttm_ref_object_base_unref(tfile, ctx->base.hash.key, TTM_REF_USAGE); 546 return ttm_ref_object_base_unref(tfile, arg->cid, TTM_REF_USAGE);
401out:
402 vmw_resource_unreference(&res);
403 return ret;
404} 547}
405 548
406int vmw_context_define_ioctl(struct drm_device *dev, void *data, 549int vmw_context_define_ioctl(struct drm_device *dev, void *data,
@@ -438,7 +581,7 @@ int vmw_context_define_ioctl(struct drm_device *dev, void *data,
438 goto out_unlock; 581 goto out_unlock;
439 } 582 }
440 583
441 ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); 584 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
442 if (unlikely(ctx == NULL)) { 585 if (unlikely(ctx == NULL)) {
443 ttm_mem_global_free(vmw_mem_glob(dev_priv), 586 ttm_mem_global_free(vmw_mem_glob(dev_priv),
444 vmw_user_context_size); 587 vmw_user_context_size);
@@ -467,7 +610,7 @@ int vmw_context_define_ioctl(struct drm_device *dev, void *data,
467 goto out_err; 610 goto out_err;
468 } 611 }
469 612
470 arg->cid = res->id; 613 arg->cid = ctx->base.hash.key;
471out_err: 614out_err:
472 vmw_resource_unreference(&res); 615 vmw_resource_unreference(&res);
473out_unlock: 616out_unlock:
@@ -476,30 +619,13 @@ out_unlock:
476 619
477} 620}
478 621
479int vmw_context_check(struct vmw_private *dev_priv, 622/**
480 struct ttm_object_file *tfile, 623 * struct vmw_bpp - Bits per pixel info for surface storage size computation.
481 int id, 624 *
482 struct vmw_resource **p_res) 625 * @bpp: Bits per pixel.
483{ 626 * @s_bpp: Stride bits per pixel. See definition below.
484 struct vmw_resource *res; 627 *
485 int ret = 0; 628 */
486
487 read_lock(&dev_priv->resource_lock);
488 res = idr_find(&dev_priv->context_idr, id);
489 if (res && res->avail) {
490 struct vmw_user_context *ctx =
491 container_of(res, struct vmw_user_context, res);
492 if (ctx->base.tfile != tfile && !ctx->base.shareable)
493 ret = -EPERM;
494 if (p_res)
495 *p_res = vmw_resource_reference(res);
496 } else
497 ret = -EINVAL;
498 read_unlock(&dev_priv->resource_lock);
499
500 return ret;
501}
502
503struct vmw_bpp { 629struct vmw_bpp {
504 uint8_t bpp; 630 uint8_t bpp;
505 uint8_t s_bpp; 631 uint8_t s_bpp;
@@ -573,9 +699,8 @@ static const struct vmw_bpp vmw_sf_bpp[] = {
573 699
574 700
575/** 701/**
576 * Surface management. 702 * struct vmw_surface_dma - SVGA3D DMA command
577 */ 703 */
578
579struct vmw_surface_dma { 704struct vmw_surface_dma {
580 SVGA3dCmdHeader header; 705 SVGA3dCmdHeader header;
581 SVGA3dCmdSurfaceDMA body; 706 SVGA3dCmdSurfaceDMA body;
@@ -583,11 +708,17 @@ struct vmw_surface_dma {
583 SVGA3dCmdSurfaceDMASuffix suffix; 708 SVGA3dCmdSurfaceDMASuffix suffix;
584}; 709};
585 710
711/**
712 * struct vmw_surface_define - SVGA3D Surface Define command
713 */
586struct vmw_surface_define { 714struct vmw_surface_define {
587 SVGA3dCmdHeader header; 715 SVGA3dCmdHeader header;
588 SVGA3dCmdDefineSurface body; 716 SVGA3dCmdDefineSurface body;
589}; 717};
590 718
719/**
720 * struct vmw_surface_destroy - SVGA3D Surface Destroy command
721 */
591struct vmw_surface_destroy { 722struct vmw_surface_destroy {
592 SVGA3dCmdHeader header; 723 SVGA3dCmdHeader header;
593 SVGA3dCmdDestroySurface body; 724 SVGA3dCmdDestroySurface body;
@@ -688,7 +819,6 @@ static void vmw_surface_define_encode(const struct vmw_surface *srf,
688 } 819 }
689} 820}
690 821
691
692/** 822/**
693 * vmw_surface_dma_encode - Encode a surface_dma command. 823 * vmw_surface_dma_encode - Encode a surface_dma command.
694 * 824 *
@@ -748,6 +878,15 @@ static void vmw_surface_dma_encode(struct vmw_surface *srf,
748}; 878};
749 879
750 880
881/**
882 * vmw_hw_surface_destroy - destroy a Device surface
883 *
884 * @res: Pointer to a struct vmw_resource embedded in a struct
885 * vmw_surface.
886 *
887 * Destroys a the device surface associated with a struct vmw_surface if
888 * any, and adjusts accounting and resource count accordingly.
889 */
751static void vmw_hw_surface_destroy(struct vmw_resource *res) 890static void vmw_hw_surface_destroy(struct vmw_resource *res)
752{ 891{
753 892
@@ -774,47 +913,30 @@ static void vmw_hw_surface_destroy(struct vmw_resource *res)
774 */ 913 */
775 914
776 mutex_lock(&dev_priv->cmdbuf_mutex); 915 mutex_lock(&dev_priv->cmdbuf_mutex);
777 srf = container_of(res, struct vmw_surface, res); 916 srf = vmw_res_to_srf(res);
778 dev_priv->used_memory_size -= srf->backup_size; 917 dev_priv->used_memory_size -= res->backup_size;
779 mutex_unlock(&dev_priv->cmdbuf_mutex); 918 mutex_unlock(&dev_priv->cmdbuf_mutex);
780
781 } 919 }
782 vmw_3d_resource_dec(dev_priv, false); 920 vmw_3d_resource_dec(dev_priv, false);
783} 921}
784 922
785void vmw_surface_res_free(struct vmw_resource *res)
786{
787 struct vmw_surface *srf = container_of(res, struct vmw_surface, res);
788
789 if (srf->backup)
790 ttm_bo_unref(&srf->backup);
791 kfree(srf->offsets);
792 kfree(srf->sizes);
793 kfree(srf->snooper.image);
794 kfree(srf);
795}
796
797
798/** 923/**
799 * vmw_surface_do_validate - make a surface available to the device. 924 * vmw_legacy_srf_create - Create a device surface as part of the
925 * resource validation process.
800 * 926 *
801 * @dev_priv: Pointer to a device private struct. 927 * @res: Pointer to a struct vmw_surface.
802 * @srf: Pointer to a struct vmw_surface.
803 * 928 *
804 * If the surface doesn't have a hw id, allocate one, and optionally 929 * If the surface doesn't have a hw id.
805 * DMA the backed up surface contents to the device.
806 * 930 *
807 * Returns -EBUSY if there wasn't sufficient device resources to 931 * Returns -EBUSY if there wasn't sufficient device resources to
808 * complete the validation. Retry after freeing up resources. 932 * complete the validation. Retry after freeing up resources.
809 * 933 *
810 * May return other errors if the kernel is out of guest resources. 934 * May return other errors if the kernel is out of guest resources.
811 */ 935 */
812int vmw_surface_do_validate(struct vmw_private *dev_priv, 936static int vmw_legacy_srf_create(struct vmw_resource *res)
813 struct vmw_surface *srf)
814{ 937{
815 struct vmw_resource *res = &srf->res; 938 struct vmw_private *dev_priv = res->dev_priv;
816 struct list_head val_list; 939 struct vmw_surface *srf;
817 struct ttm_validate_buffer val_buf;
818 uint32_t submit_size; 940 uint32_t submit_size;
819 uint8_t *cmd; 941 uint8_t *cmd;
820 int ret; 942 int ret;
@@ -822,324 +944,261 @@ int vmw_surface_do_validate(struct vmw_private *dev_priv,
822 if (likely(res->id != -1)) 944 if (likely(res->id != -1))
823 return 0; 945 return 0;
824 946
825 if (unlikely(dev_priv->used_memory_size + srf->backup_size >= 947 srf = vmw_res_to_srf(res);
948 if (unlikely(dev_priv->used_memory_size + res->backup_size >=
826 dev_priv->memory_size)) 949 dev_priv->memory_size))
827 return -EBUSY; 950 return -EBUSY;
828 951
829 /* 952 /*
830 * Reserve- and validate the backup DMA bo.
831 */
832
833 if (srf->backup) {
834 INIT_LIST_HEAD(&val_list);
835 val_buf.bo = ttm_bo_reference(srf->backup);
836 list_add_tail(&val_buf.head, &val_list);
837 ret = ttm_eu_reserve_buffers(&val_list);
838 if (unlikely(ret != 0))
839 goto out_no_reserve;
840
841 ret = ttm_bo_validate(srf->backup, &vmw_srf_placement,
842 true, false, false);
843 if (unlikely(ret != 0))
844 goto out_no_validate;
845 }
846
847 /*
848 * Alloc id for the resource. 953 * Alloc id for the resource.
849 */ 954 */
850 955
851 ret = vmw_resource_alloc_id(dev_priv, res); 956 ret = vmw_resource_alloc_id(res);
852 if (unlikely(ret != 0)) { 957 if (unlikely(ret != 0)) {
853 DRM_ERROR("Failed to allocate a surface id.\n"); 958 DRM_ERROR("Failed to allocate a surface id.\n");
854 goto out_no_id; 959 goto out_no_id;
855 } 960 }
961
856 if (unlikely(res->id >= SVGA3D_MAX_SURFACE_IDS)) { 962 if (unlikely(res->id >= SVGA3D_MAX_SURFACE_IDS)) {
857 ret = -EBUSY; 963 ret = -EBUSY;
858 goto out_no_fifo; 964 goto out_no_fifo;
859 } 965 }
860 966
861
862 /* 967 /*
863 * Encode surface define- and dma commands. 968 * Encode surface define- commands.
864 */ 969 */
865 970
866 submit_size = vmw_surface_define_size(srf); 971 submit_size = vmw_surface_define_size(srf);
867 if (srf->backup)
868 submit_size += vmw_surface_dma_size(srf);
869
870 cmd = vmw_fifo_reserve(dev_priv, submit_size); 972 cmd = vmw_fifo_reserve(dev_priv, submit_size);
871 if (unlikely(cmd == NULL)) { 973 if (unlikely(cmd == NULL)) {
872 DRM_ERROR("Failed reserving FIFO space for surface " 974 DRM_ERROR("Failed reserving FIFO space for surface "
873 "validation.\n"); 975 "creation.\n");
874 ret = -ENOMEM; 976 ret = -ENOMEM;
875 goto out_no_fifo; 977 goto out_no_fifo;
876 } 978 }
877 979
878 vmw_surface_define_encode(srf, cmd); 980 vmw_surface_define_encode(srf, cmd);
879 if (srf->backup) {
880 SVGAGuestPtr ptr;
881
882 cmd += vmw_surface_define_size(srf);
883 vmw_bo_get_guest_ptr(srf->backup, &ptr);
884 vmw_surface_dma_encode(srf, cmd, &ptr, true);
885 }
886
887 vmw_fifo_commit(dev_priv, submit_size); 981 vmw_fifo_commit(dev_priv, submit_size);
888
889 /*
890 * Create a fence object and fence the backup buffer.
891 */
892
893 if (srf->backup) {
894 struct vmw_fence_obj *fence;
895
896 (void) vmw_execbuf_fence_commands(NULL, dev_priv,
897 &fence, NULL);
898 ttm_eu_fence_buffer_objects(&val_list, fence);
899 if (likely(fence != NULL))
900 vmw_fence_obj_unreference(&fence);
901 ttm_bo_unref(&val_buf.bo);
902 ttm_bo_unref(&srf->backup);
903 }
904
905 /* 982 /*
906 * Surface memory usage accounting. 983 * Surface memory usage accounting.
907 */ 984 */
908 985
909 dev_priv->used_memory_size += srf->backup_size; 986 dev_priv->used_memory_size += res->backup_size;
910
911 return 0; 987 return 0;
912 988
913out_no_fifo: 989out_no_fifo:
914 vmw_resource_release_id(res); 990 vmw_resource_release_id(res);
915out_no_id: 991out_no_id:
916out_no_validate:
917 if (srf->backup)
918 ttm_eu_backoff_reservation(&val_list);
919out_no_reserve:
920 if (srf->backup)
921 ttm_bo_unref(&val_buf.bo);
922 return ret; 992 return ret;
923} 993}
924 994
925/** 995/**
926 * vmw_surface_evict - Evict a hw surface. 996 * vmw_legacy_srf_dma - Copy backup data to or from a legacy surface.
927 * 997 *
928 * @dev_priv: Pointer to a device private struct. 998 * @res: Pointer to a struct vmw_res embedded in a struct
929 * @srf: Pointer to a struct vmw_surface 999 * vmw_surface.
1000 * @val_buf: Pointer to a struct ttm_validate_buffer containing
1001 * information about the backup buffer.
1002 * @bind: Boolean wether to DMA to the surface.
930 * 1003 *
931 * DMA the contents of a hw surface to a backup guest buffer object, 1004 * Transfer backup data to or from a legacy surface as part of the
932 * and destroy the hw surface, releasing its id. 1005 * validation process.
1006 * May return other errors if the kernel is out of guest resources.
1007 * The backup buffer will be fenced or idle upon successful completion,
1008 * and if the surface needs persistent backup storage, the backup buffer
1009 * will also be returned reserved iff @bind is true.
933 */ 1010 */
934int vmw_surface_evict(struct vmw_private *dev_priv, 1011static int vmw_legacy_srf_dma(struct vmw_resource *res,
935 struct vmw_surface *srf) 1012 struct ttm_validate_buffer *val_buf,
1013 bool bind)
936{ 1014{
937 struct vmw_resource *res = &srf->res; 1015 SVGAGuestPtr ptr;
938 struct list_head val_list; 1016 struct vmw_fence_obj *fence;
939 struct ttm_validate_buffer val_buf;
940 uint32_t submit_size; 1017 uint32_t submit_size;
1018 struct vmw_surface *srf = vmw_res_to_srf(res);
941 uint8_t *cmd; 1019 uint8_t *cmd;
942 int ret; 1020 struct vmw_private *dev_priv = res->dev_priv;
943 struct vmw_fence_obj *fence;
944 SVGAGuestPtr ptr;
945
946 BUG_ON(res->id == -1);
947
948 /*
949 * Create a surface backup buffer object.
950 */
951
952 if (!srf->backup) {
953 ret = ttm_bo_create(&dev_priv->bdev, srf->backup_size,
954 ttm_bo_type_device,
955 &vmw_srf_placement, 0, true,
956 NULL, &srf->backup);
957 if (unlikely(ret != 0))
958 return ret;
959 }
960
961 /*
962 * Reserve- and validate the backup DMA bo.
963 */
964
965 INIT_LIST_HEAD(&val_list);
966 val_buf.bo = ttm_bo_reference(srf->backup);
967 list_add_tail(&val_buf.head, &val_list);
968 ret = ttm_eu_reserve_buffers(&val_list);
969 if (unlikely(ret != 0))
970 goto out_no_reserve;
971
972 ret = ttm_bo_validate(srf->backup, &vmw_srf_placement,
973 true, false, false);
974 if (unlikely(ret != 0))
975 goto out_no_validate;
976
977 1021
978 /* 1022 BUG_ON(val_buf->bo == NULL);
979 * Encode the dma- and surface destroy commands.
980 */
981 1023
982 submit_size = vmw_surface_dma_size(srf) + vmw_surface_destroy_size(); 1024 submit_size = vmw_surface_dma_size(srf);
983 cmd = vmw_fifo_reserve(dev_priv, submit_size); 1025 cmd = vmw_fifo_reserve(dev_priv, submit_size);
984 if (unlikely(cmd == NULL)) { 1026 if (unlikely(cmd == NULL)) {
985 DRM_ERROR("Failed reserving FIFO space for surface " 1027 DRM_ERROR("Failed reserving FIFO space for surface "
986 "eviction.\n"); 1028 "DMA.\n");
987 ret = -ENOMEM; 1029 return -ENOMEM;
988 goto out_no_fifo;
989 } 1030 }
1031 vmw_bo_get_guest_ptr(val_buf->bo, &ptr);
1032 vmw_surface_dma_encode(srf, cmd, &ptr, bind);
990 1033
991 vmw_bo_get_guest_ptr(srf->backup, &ptr);
992 vmw_surface_dma_encode(srf, cmd, &ptr, false);
993 cmd += vmw_surface_dma_size(srf);
994 vmw_surface_destroy_encode(res->id, cmd);
995 vmw_fifo_commit(dev_priv, submit_size); 1034 vmw_fifo_commit(dev_priv, submit_size);
996 1035
997 /* 1036 /*
998 * Surface memory usage accounting. 1037 * Create a fence object and fence the backup buffer.
999 */
1000
1001 dev_priv->used_memory_size -= srf->backup_size;
1002
1003 /*
1004 * Create a fence object and fence the DMA buffer.
1005 */ 1038 */
1006 1039
1007 (void) vmw_execbuf_fence_commands(NULL, dev_priv, 1040 (void) vmw_execbuf_fence_commands(NULL, dev_priv,
1008 &fence, NULL); 1041 &fence, NULL);
1009 ttm_eu_fence_buffer_objects(&val_list, fence);
1010 if (likely(fence != NULL))
1011 vmw_fence_obj_unreference(&fence);
1012 ttm_bo_unref(&val_buf.bo);
1013 1042
1014 /* 1043 vmw_fence_single_bo(val_buf->bo, fence);
1015 * Release the surface ID.
1016 */
1017 1044
1018 vmw_resource_release_id(res); 1045 if (likely(fence != NULL))
1046 vmw_fence_obj_unreference(&fence);
1019 1047
1020 return 0; 1048 return 0;
1049}
1021 1050
1022out_no_fifo: 1051/**
1023out_no_validate: 1052 * vmw_legacy_srf_bind - Perform a legacy surface bind as part of the
1024 if (srf->backup) 1053 * surface validation process.
1025 ttm_eu_backoff_reservation(&val_list); 1054 *
1026out_no_reserve: 1055 * @res: Pointer to a struct vmw_res embedded in a struct
1027 ttm_bo_unref(&val_buf.bo); 1056 * vmw_surface.
1028 ttm_bo_unref(&srf->backup); 1057 * @val_buf: Pointer to a struct ttm_validate_buffer containing
1029 return ret; 1058 * information about the backup buffer.
1059 *
1060 * This function will copy backup data to the surface if the
1061 * backup buffer is dirty.
1062 */
1063static int vmw_legacy_srf_bind(struct vmw_resource *res,
1064 struct ttm_validate_buffer *val_buf)
1065{
1066 if (!res->backup_dirty)
1067 return 0;
1068
1069 return vmw_legacy_srf_dma(res, val_buf, true);
1030} 1070}
1031 1071
1032 1072
1033/** 1073/**
1034 * vmw_surface_validate - make a surface available to the device, evicting 1074 * vmw_legacy_srf_unbind - Perform a legacy surface unbind as part of the
1035 * other surfaces if needed. 1075 * surface eviction process.
1036 * 1076 *
1037 * @dev_priv: Pointer to a device private struct. 1077 * @res: Pointer to a struct vmw_res embedded in a struct
1038 * @srf: Pointer to a struct vmw_surface. 1078 * vmw_surface.
1079 * @val_buf: Pointer to a struct ttm_validate_buffer containing
1080 * information about the backup buffer.
1039 * 1081 *
1040 * Try to validate a surface and if it fails due to limited device resources, 1082 * This function will copy backup data from the surface.
1041 * repeatedly try to evict other surfaces until the request can be 1083 */
1042 * acommodated. 1084static int vmw_legacy_srf_unbind(struct vmw_resource *res,
1085 bool readback,
1086 struct ttm_validate_buffer *val_buf)
1087{
1088 if (unlikely(readback))
1089 return vmw_legacy_srf_dma(res, val_buf, false);
1090 return 0;
1091}
1092
1093/**
1094 * vmw_legacy_srf_destroy - Destroy a device surface as part of a
1095 * resource eviction process.
1043 * 1096 *
1044 * May return errors if out of resources. 1097 * @res: Pointer to a struct vmw_res embedded in a struct
1098 * vmw_surface.
1045 */ 1099 */
1046int vmw_surface_validate(struct vmw_private *dev_priv, 1100static int vmw_legacy_srf_destroy(struct vmw_resource *res)
1047 struct vmw_surface *srf)
1048{ 1101{
1049 int ret; 1102 struct vmw_private *dev_priv = res->dev_priv;
1050 struct vmw_surface *evict_srf; 1103 uint32_t submit_size;
1104 uint8_t *cmd;
1051 1105
1052 do { 1106 BUG_ON(res->id == -1);
1053 write_lock(&dev_priv->resource_lock);
1054 list_del_init(&srf->lru_head);
1055 write_unlock(&dev_priv->resource_lock);
1056 1107
1057 ret = vmw_surface_do_validate(dev_priv, srf); 1108 /*
1058 if (likely(ret != -EBUSY)) 1109 * Encode the dma- and surface destroy commands.
1059 break; 1110 */
1060 1111
1061 write_lock(&dev_priv->resource_lock); 1112 submit_size = vmw_surface_destroy_size();
1062 if (list_empty(&dev_priv->surface_lru)) { 1113 cmd = vmw_fifo_reserve(dev_priv, submit_size);
1063 DRM_ERROR("Out of device memory for surfaces.\n"); 1114 if (unlikely(cmd == NULL)) {
1064 ret = -EBUSY; 1115 DRM_ERROR("Failed reserving FIFO space for surface "
1065 write_unlock(&dev_priv->resource_lock); 1116 "eviction.\n");
1066 break; 1117 return -ENOMEM;
1067 } 1118 }
1068 1119
1069 evict_srf = vmw_surface_reference 1120 vmw_surface_destroy_encode(res->id, cmd);
1070 (list_first_entry(&dev_priv->surface_lru, 1121 vmw_fifo_commit(dev_priv, submit_size);
1071 struct vmw_surface,
1072 lru_head));
1073 list_del_init(&evict_srf->lru_head);
1074 1122
1075 write_unlock(&dev_priv->resource_lock); 1123 /*
1076 (void) vmw_surface_evict(dev_priv, evict_srf); 1124 * Surface memory usage accounting.
1125 */
1077 1126
1078 vmw_surface_unreference(&evict_srf); 1127 dev_priv->used_memory_size -= res->backup_size;
1079 1128
1080 } while (1); 1129 /*
1130 * Release the surface ID.
1131 */
1081 1132
1082 if (unlikely(ret != 0 && srf->res.id != -1)) { 1133 vmw_resource_release_id(res);
1083 write_lock(&dev_priv->resource_lock);
1084 list_add_tail(&srf->lru_head, &dev_priv->surface_lru);
1085 write_unlock(&dev_priv->resource_lock);
1086 }
1087 1134
1088 return ret; 1135 return 0;
1089} 1136}
1090 1137
1091 1138
1092/** 1139/**
1093 * vmw_surface_remove_from_lists - Remove surface resources from lookup lists 1140 * vmw_surface_init - initialize a struct vmw_surface
1094 * 1141 *
1095 * @res: Pointer to a struct vmw_resource embedded in a struct vmw_surface 1142 * @dev_priv: Pointer to a device private struct.
1096 * 1143 * @srf: Pointer to the struct vmw_surface to initialize.
1097 * As part of the resource destruction, remove the surface from any 1144 * @res_free: Pointer to a resource destructor used to free
1098 * lookup lists. 1145 * the object.
1099 */ 1146 */
1100static void vmw_surface_remove_from_lists(struct vmw_resource *res) 1147static int vmw_surface_init(struct vmw_private *dev_priv,
1101{ 1148 struct vmw_surface *srf,
1102 struct vmw_surface *srf = container_of(res, struct vmw_surface, res); 1149 void (*res_free) (struct vmw_resource *res))
1103
1104 list_del_init(&srf->lru_head);
1105}
1106
1107int vmw_surface_init(struct vmw_private *dev_priv,
1108 struct vmw_surface *srf,
1109 void (*res_free) (struct vmw_resource *res))
1110{ 1150{
1111 int ret; 1151 int ret;
1112 struct vmw_resource *res = &srf->res; 1152 struct vmw_resource *res = &srf->res;
1113 1153
1114 BUG_ON(res_free == NULL); 1154 BUG_ON(res_free == NULL);
1115 INIT_LIST_HEAD(&srf->lru_head); 1155 (void) vmw_3d_resource_inc(dev_priv, false);
1116 ret = vmw_resource_init(dev_priv, res, &dev_priv->surface_idr, 1156 ret = vmw_resource_init(dev_priv, res, true, res_free,
1117 VMW_RES_SURFACE, true, res_free, 1157 &vmw_legacy_surface_func);
1118 vmw_surface_remove_from_lists);
1119 1158
1120 if (unlikely(ret != 0)) 1159 if (unlikely(ret != 0)) {
1160 vmw_3d_resource_dec(dev_priv, false);
1121 res_free(res); 1161 res_free(res);
1162 return ret;
1163 }
1122 1164
1123 /* 1165 /*
1124 * The surface won't be visible to hardware until a 1166 * The surface won't be visible to hardware until a
1125 * surface validate. 1167 * surface validate.
1126 */ 1168 */
1127 1169
1128 (void) vmw_3d_resource_inc(dev_priv, false);
1129 vmw_resource_activate(res, vmw_hw_surface_destroy); 1170 vmw_resource_activate(res, vmw_hw_surface_destroy);
1130 return ret; 1171 return ret;
1131} 1172}
1132 1173
1174/**
1175 * vmw_user_surface_base_to_res - TTM base object to resource converter for
1176 * user visible surfaces
1177 *
1178 * @base: Pointer to a TTM base object
1179 *
1180 * Returns the struct vmw_resource embedded in a struct vmw_surface
1181 * for the user-visible object identified by the TTM base object @base.
1182 */
1183static struct vmw_resource *
1184vmw_user_surface_base_to_res(struct ttm_base_object *base)
1185{
1186 return &(container_of(base, struct vmw_user_surface, base)->srf.res);
1187}
1188
1189/**
1190 * vmw_user_surface_free - User visible surface resource destructor
1191 *
1192 * @res: A struct vmw_resource embedded in a struct vmw_surface.
1193 */
1133static void vmw_user_surface_free(struct vmw_resource *res) 1194static void vmw_user_surface_free(struct vmw_resource *res)
1134{ 1195{
1135 struct vmw_surface *srf = container_of(res, struct vmw_surface, res); 1196 struct vmw_surface *srf = vmw_res_to_srf(res);
1136 struct vmw_user_surface *user_srf = 1197 struct vmw_user_surface *user_srf =
1137 container_of(srf, struct vmw_user_surface, srf); 1198 container_of(srf, struct vmw_user_surface, srf);
1138 struct vmw_private *dev_priv = srf->res.dev_priv; 1199 struct vmw_private *dev_priv = srf->res.dev_priv;
1139 uint32_t size = user_srf->size; 1200 uint32_t size = user_srf->size;
1140 1201
1141 if (srf->backup)
1142 ttm_bo_unref(&srf->backup);
1143 kfree(srf->offsets); 1202 kfree(srf->offsets);
1144 kfree(srf->sizes); 1203 kfree(srf->sizes);
1145 kfree(srf->snooper.image); 1204 kfree(srf->snooper.image);
@@ -1148,108 +1207,14 @@ static void vmw_user_surface_free(struct vmw_resource *res)
1148} 1207}
1149 1208
1150/** 1209/**
1151 * vmw_resource_unreserve - unreserve resources previously reserved for 1210 * vmw_user_surface_free - User visible surface TTM base object destructor
1152 * command submission.
1153 * 1211 *
1154 * @list_head: list of resources to unreserve. 1212 * @p_base: Pointer to a pointer to a TTM base object
1213 * embedded in a struct vmw_user_surface.
1155 * 1214 *
1156 * Currently only surfaces are considered, and unreserving a surface 1215 * Drops the base object's reference on its resource, and the
1157 * means putting it back on the device's surface lru list, 1216 * pointer pointed to by *p_base is set to NULL.
1158 * so that it can be evicted if necessary.
1159 * This function traverses the resource list and
1160 * checks whether resources are surfaces, and in that case puts them back
1161 * on the device's surface LRU list.
1162 */ 1217 */
1163void vmw_resource_unreserve(struct list_head *list)
1164{
1165 struct vmw_resource *res;
1166 struct vmw_surface *srf;
1167 rwlock_t *lock = NULL;
1168
1169 list_for_each_entry(res, list, validate_head) {
1170
1171 if (res->res_free != &vmw_surface_res_free &&
1172 res->res_free != &vmw_user_surface_free)
1173 continue;
1174
1175 if (unlikely(lock == NULL)) {
1176 lock = &res->dev_priv->resource_lock;
1177 write_lock(lock);
1178 }
1179
1180 srf = container_of(res, struct vmw_surface, res);
1181 list_del_init(&srf->lru_head);
1182 list_add_tail(&srf->lru_head, &res->dev_priv->surface_lru);
1183 }
1184
1185 if (lock != NULL)
1186 write_unlock(lock);
1187}
1188
1189/**
1190 * Helper function that looks either a surface or dmabuf.
1191 *
1192 * The pointer this pointed at by out_surf and out_buf needs to be null.
1193 */
1194int vmw_user_lookup_handle(struct vmw_private *dev_priv,
1195 struct ttm_object_file *tfile,
1196 uint32_t handle,
1197 struct vmw_surface **out_surf,
1198 struct vmw_dma_buffer **out_buf)
1199{
1200 int ret;
1201
1202 BUG_ON(*out_surf || *out_buf);
1203
1204 ret = vmw_user_surface_lookup_handle(dev_priv, tfile, handle, out_surf);
1205 if (!ret)
1206 return 0;
1207
1208 ret = vmw_user_dmabuf_lookup(tfile, handle, out_buf);
1209 return ret;
1210}
1211
1212
1213int vmw_user_surface_lookup_handle(struct vmw_private *dev_priv,
1214 struct ttm_object_file *tfile,
1215 uint32_t handle, struct vmw_surface **out)
1216{
1217 struct vmw_resource *res;
1218 struct vmw_surface *srf;
1219 struct vmw_user_surface *user_srf;
1220 struct ttm_base_object *base;
1221 int ret = -EINVAL;
1222
1223 base = ttm_base_object_lookup(tfile, handle);
1224 if (unlikely(base == NULL))
1225 return -EINVAL;
1226
1227 if (unlikely(base->object_type != VMW_RES_SURFACE))
1228 goto out_bad_resource;
1229
1230 user_srf = container_of(base, struct vmw_user_surface, base);
1231 srf = &user_srf->srf;
1232 res = &srf->res;
1233
1234 read_lock(&dev_priv->resource_lock);
1235
1236 if (!res->avail || res->res_free != &vmw_user_surface_free) {
1237 read_unlock(&dev_priv->resource_lock);
1238 goto out_bad_resource;
1239 }
1240
1241 kref_get(&res->kref);
1242 read_unlock(&dev_priv->resource_lock);
1243
1244 *out = srf;
1245 ret = 0;
1246
1247out_bad_resource:
1248 ttm_base_object_unref(&base);
1249
1250 return ret;
1251}
1252
1253static void vmw_user_surface_base_release(struct ttm_base_object **p_base) 1218static void vmw_user_surface_base_release(struct ttm_base_object **p_base)
1254{ 1219{
1255 struct ttm_base_object *base = *p_base; 1220 struct ttm_base_object *base = *p_base;
@@ -1261,6 +1226,14 @@ static void vmw_user_surface_base_release(struct ttm_base_object **p_base)
1261 vmw_resource_unreference(&res); 1226 vmw_resource_unreference(&res);
1262} 1227}
1263 1228
1229/**
1230 * vmw_user_surface_destroy_ioctl - Ioctl function implementing
1231 * the user surface destroy functionality.
1232 *
1233 * @dev: Pointer to a struct drm_device.
1234 * @data: Pointer to data copied from / to user-space.
1235 * @file_priv: Pointer to a drm file private structure.
1236 */
1264int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data, 1237int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
1265 struct drm_file *file_priv) 1238 struct drm_file *file_priv)
1266{ 1239{
@@ -1270,6 +1243,14 @@ int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
1270 return ttm_ref_object_base_unref(tfile, arg->sid, TTM_REF_USAGE); 1243 return ttm_ref_object_base_unref(tfile, arg->sid, TTM_REF_USAGE);
1271} 1244}
1272 1245
1246/**
1247 * vmw_user_surface_define_ioctl - Ioctl function implementing
1248 * the user surface define functionality.
1249 *
1250 * @dev: Pointer to a struct drm_device.
1251 * @data: Pointer to data copied from / to user-space.
1252 * @file_priv: Pointer to a drm file private structure.
1253 */
1273int vmw_surface_define_ioctl(struct drm_device *dev, void *data, 1254int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
1274 struct drm_file *file_priv) 1255 struct drm_file *file_priv)
1275{ 1256{
@@ -1325,7 +1306,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
1325 goto out_unlock; 1306 goto out_unlock;
1326 } 1307 }
1327 1308
1328 user_srf = kmalloc(sizeof(*user_srf), GFP_KERNEL); 1309 user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL);
1329 if (unlikely(user_srf == NULL)) { 1310 if (unlikely(user_srf == NULL)) {
1330 ret = -ENOMEM; 1311 ret = -ENOMEM;
1331 goto out_no_user_srf; 1312 goto out_no_user_srf;
@@ -1337,7 +1318,6 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
1337 srf->flags = req->flags; 1318 srf->flags = req->flags;
1338 srf->format = req->format; 1319 srf->format = req->format;
1339 srf->scanout = req->scanout; 1320 srf->scanout = req->scanout;
1340 srf->backup = NULL;
1341 1321
1342 memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels)); 1322 memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels));
1343 srf->num_sizes = num_sizes; 1323 srf->num_sizes = num_sizes;
@@ -1365,6 +1345,10 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
1365 goto out_no_copy; 1345 goto out_no_copy;
1366 } 1346 }
1367 1347
1348 srf->base_size = *srf->sizes;
1349 srf->autogen_filter = SVGA3D_TEX_FILTER_NONE;
1350 srf->multisample_count = 1;
1351
1368 cur_bo_offset = 0; 1352 cur_bo_offset = 0;
1369 cur_offset = srf->offsets; 1353 cur_offset = srf->offsets;
1370 cur_size = srf->sizes; 1354 cur_size = srf->sizes;
@@ -1386,7 +1370,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
1386 ++cur_size; 1370 ++cur_size;
1387 } 1371 }
1388 } 1372 }
1389 srf->backup_size = cur_bo_offset; 1373 res->backup_size = cur_bo_offset;
1390 1374
1391 if (srf->scanout && 1375 if (srf->scanout &&
1392 srf->num_sizes == 1 && 1376 srf->num_sizes == 1 &&
@@ -1430,9 +1414,6 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
1430 } 1414 }
1431 1415
1432 rep->sid = user_srf->base.hash.key; 1416 rep->sid = user_srf->base.hash.key;
1433 if (rep->sid == SVGA3D_INVALID_ID)
1434 DRM_ERROR("Created bad Surface ID.\n");
1435
1436 vmw_resource_unreference(&res); 1417 vmw_resource_unreference(&res);
1437 1418
1438 ttm_read_unlock(&vmaster->lock); 1419 ttm_read_unlock(&vmaster->lock);
@@ -1450,6 +1431,14 @@ out_unlock:
1450 return ret; 1431 return ret;
1451} 1432}
1452 1433
1434/**
1435 * vmw_user_surface_define_ioctl - Ioctl function implementing
1436 * the user surface reference functionality.
1437 *
1438 * @dev: Pointer to a struct drm_device.
1439 * @data: Pointer to data copied from / to user-space.
1440 * @file_priv: Pointer to a drm file private structure.
1441 */
1453int vmw_surface_reference_ioctl(struct drm_device *dev, void *data, 1442int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
1454 struct drm_file *file_priv) 1443 struct drm_file *file_priv)
1455{ 1444{
@@ -1503,33 +1492,84 @@ out_no_reference:
1503 return ret; 1492 return ret;
1504} 1493}
1505 1494
1506int vmw_surface_check(struct vmw_private *dev_priv, 1495/**
1507 struct ttm_object_file *tfile, 1496 * vmw_user_resource_lookup_handle - lookup a struct resource from a
1508 uint32_t handle, int *id) 1497 * TTM user-space handle and perform basic type checks
1498 *
1499 * @dev_priv: Pointer to a device private struct
1500 * @tfile: Pointer to a struct ttm_object_file identifying the caller
1501 * @handle: The TTM user-space handle
1502 * @converter: Pointer to an object describing the resource type
1503 * @p_res: On successful return the location pointed to will contain
1504 * a pointer to a refcounted struct vmw_resource.
1505 *
1506 * If the handle can't be found or is associated with an incorrect resource
1507 * type, -EINVAL will be returned.
1508 */
1509int vmw_user_resource_lookup_handle(struct vmw_private *dev_priv,
1510 struct ttm_object_file *tfile,
1511 uint32_t handle,
1512 const struct vmw_user_resource_conv
1513 *converter,
1514 struct vmw_resource **p_res)
1509{ 1515{
1510 struct ttm_base_object *base; 1516 struct ttm_base_object *base;
1511 struct vmw_user_surface *user_srf; 1517 struct vmw_resource *res;
1512 1518 int ret = -EINVAL;
1513 int ret = -EPERM;
1514 1519
1515 base = ttm_base_object_lookup(tfile, handle); 1520 base = ttm_base_object_lookup(tfile, handle);
1516 if (unlikely(base == NULL)) 1521 if (unlikely(base == NULL))
1517 return -EINVAL; 1522 return -EINVAL;
1518 1523
1519 if (unlikely(base->object_type != VMW_RES_SURFACE)) 1524 if (unlikely(base->object_type != converter->object_type))
1520 goto out_bad_surface; 1525 goto out_bad_resource;
1521 1526
1522 user_srf = container_of(base, struct vmw_user_surface, base); 1527 res = converter->base_obj_to_res(base);
1523 *id = user_srf->srf.res.id;
1524 ret = 0;
1525 1528
1526out_bad_surface: 1529 read_lock(&dev_priv->resource_lock);
1527 /** 1530 if (!res->avail || res->res_free != converter->res_free) {
1528 * FIXME: May deadlock here when called from the 1531 read_unlock(&dev_priv->resource_lock);
1529 * command parsing code. 1532 goto out_bad_resource;
1530 */ 1533 }
1531 1534
1535 kref_get(&res->kref);
1536 read_unlock(&dev_priv->resource_lock);
1537
1538 *p_res = res;
1539 ret = 0;
1540
1541out_bad_resource:
1532 ttm_base_object_unref(&base); 1542 ttm_base_object_unref(&base);
1543
1544 return ret;
1545}
1546
1547/**
1548 * Helper function that looks either a surface or dmabuf.
1549 *
1550 * The pointer this pointed at by out_surf and out_buf needs to be null.
1551 */
1552int vmw_user_lookup_handle(struct vmw_private *dev_priv,
1553 struct ttm_object_file *tfile,
1554 uint32_t handle,
1555 struct vmw_surface **out_surf,
1556 struct vmw_dma_buffer **out_buf)
1557{
1558 struct vmw_resource *res;
1559 int ret;
1560
1561 BUG_ON(*out_surf || *out_buf);
1562
1563 ret = vmw_user_resource_lookup_handle(dev_priv, tfile, handle,
1564 user_surface_converter,
1565 &res);
1566 if (!ret) {
1567 *out_surf = vmw_res_to_srf(res);
1568 return 0;
1569 }
1570
1571 *out_surf = NULL;
1572 ret = vmw_user_dmabuf_lookup(tfile, handle, out_buf);
1533 return ret; 1573 return ret;
1534} 1574}
1535 1575
@@ -1558,7 +1598,7 @@ int vmw_dmabuf_init(struct vmw_private *dev_priv,
1558 acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct vmw_dma_buffer)); 1598 acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct vmw_dma_buffer));
1559 memset(vmw_bo, 0, sizeof(*vmw_bo)); 1599 memset(vmw_bo, 0, sizeof(*vmw_bo));
1560 1600
1561 INIT_LIST_HEAD(&vmw_bo->validate_list); 1601 INIT_LIST_HEAD(&vmw_bo->res_list);
1562 1602
1563 ret = ttm_bo_init(bdev, &vmw_bo->base, size, 1603 ret = ttm_bo_init(bdev, &vmw_bo->base, size,
1564 ttm_bo_type_device, placement, 1604 ttm_bo_type_device, placement,
@@ -1590,6 +1630,59 @@ static void vmw_user_dmabuf_release(struct ttm_base_object **p_base)
1590 ttm_bo_unref(&bo); 1630 ttm_bo_unref(&bo);
1591} 1631}
1592 1632
1633/**
1634 * vmw_user_dmabuf_alloc - Allocate a user dma buffer
1635 *
1636 * @dev_priv: Pointer to a struct device private.
1637 * @tfile: Pointer to a struct ttm_object_file on which to register the user
1638 * object.
1639 * @size: Size of the dma buffer.
1640 * @shareable: Boolean whether the buffer is shareable with other open files.
1641 * @handle: Pointer to where the handle value should be assigned.
1642 * @p_dma_buf: Pointer to where the refcounted struct vmw_dma_buffer pointer
1643 * should be assigned.
1644 */
1645int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv,
1646 struct ttm_object_file *tfile,
1647 uint32_t size,
1648 bool shareable,
1649 uint32_t *handle,
1650 struct vmw_dma_buffer **p_dma_buf)
1651{
1652 struct vmw_user_dma_buffer *user_bo;
1653 struct ttm_buffer_object *tmp;
1654 int ret;
1655
1656 user_bo = kzalloc(sizeof(*user_bo), GFP_KERNEL);
1657 if (unlikely(user_bo == NULL)) {
1658 DRM_ERROR("Failed to allocate a buffer.\n");
1659 return -ENOMEM;
1660 }
1661
1662 ret = vmw_dmabuf_init(dev_priv, &user_bo->dma, size,
1663 &vmw_vram_sys_placement, true,
1664 &vmw_user_dmabuf_destroy);
1665 if (unlikely(ret != 0))
1666 return ret;
1667
1668 tmp = ttm_bo_reference(&user_bo->dma.base);
1669 ret = ttm_base_object_init(tfile,
1670 &user_bo->base,
1671 shareable,
1672 ttm_buffer_type,
1673 &vmw_user_dmabuf_release, NULL);
1674 if (unlikely(ret != 0)) {
1675 ttm_bo_unref(&tmp);
1676 goto out_no_base_object;
1677 }
1678
1679 *p_dma_buf = &user_bo->dma;
1680 *handle = user_bo->base.hash.key;
1681
1682out_no_base_object:
1683 return ret;
1684}
1685
1593int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data, 1686int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
1594 struct drm_file *file_priv) 1687 struct drm_file *file_priv)
1595{ 1688{
@@ -1598,44 +1691,27 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
1598 (union drm_vmw_alloc_dmabuf_arg *)data; 1691 (union drm_vmw_alloc_dmabuf_arg *)data;
1599 struct drm_vmw_alloc_dmabuf_req *req = &arg->req; 1692 struct drm_vmw_alloc_dmabuf_req *req = &arg->req;
1600 struct drm_vmw_dmabuf_rep *rep = &arg->rep; 1693 struct drm_vmw_dmabuf_rep *rep = &arg->rep;
1601 struct vmw_user_dma_buffer *vmw_user_bo; 1694 struct vmw_dma_buffer *dma_buf;
1602 struct ttm_buffer_object *tmp; 1695 uint32_t handle;
1603 struct vmw_master *vmaster = vmw_master(file_priv->master); 1696 struct vmw_master *vmaster = vmw_master(file_priv->master);
1604 int ret; 1697 int ret;
1605 1698
1606 vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL);
1607 if (unlikely(vmw_user_bo == NULL))
1608 return -ENOMEM;
1609
1610 ret = ttm_read_lock(&vmaster->lock, true); 1699 ret = ttm_read_lock(&vmaster->lock, true);
1611 if (unlikely(ret != 0)) { 1700 if (unlikely(ret != 0))
1612 kfree(vmw_user_bo);
1613 return ret; 1701 return ret;
1614 }
1615 1702
1616 ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, req->size, 1703 ret = vmw_user_dmabuf_alloc(dev_priv, vmw_fpriv(file_priv)->tfile,
1617 &vmw_vram_sys_placement, true, 1704 req->size, false, &handle, &dma_buf);
1618 &vmw_user_dmabuf_destroy);
1619 if (unlikely(ret != 0)) 1705 if (unlikely(ret != 0))
1620 goto out_no_dmabuf; 1706 goto out_no_dmabuf;
1621 1707
1622 tmp = ttm_bo_reference(&vmw_user_bo->dma.base); 1708 rep->handle = handle;
1623 ret = ttm_base_object_init(vmw_fpriv(file_priv)->tfile, 1709 rep->map_handle = dma_buf->base.addr_space_offset;
1624 &vmw_user_bo->base, 1710 rep->cur_gmr_id = handle;
1625 false, 1711 rep->cur_gmr_offset = 0;
1626 ttm_buffer_type, 1712
1627 &vmw_user_dmabuf_release, NULL); 1713 vmw_dmabuf_unreference(&dma_buf);
1628 if (unlikely(ret != 0))
1629 goto out_no_base_object;
1630 else {
1631 rep->handle = vmw_user_bo->base.hash.key;
1632 rep->map_handle = vmw_user_bo->dma.base.addr_space_offset;
1633 rep->cur_gmr_id = vmw_user_bo->base.hash.key;
1634 rep->cur_gmr_offset = 0;
1635 }
1636 1714
1637out_no_base_object:
1638 ttm_bo_unref(&tmp);
1639out_no_dmabuf: 1715out_no_dmabuf:
1640 ttm_read_unlock(&vmaster->lock); 1716 ttm_read_unlock(&vmaster->lock);
1641 1717
@@ -1653,27 +1729,6 @@ int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data,
1653 TTM_REF_USAGE); 1729 TTM_REF_USAGE);
1654} 1730}
1655 1731
1656uint32_t vmw_dmabuf_validate_node(struct ttm_buffer_object *bo,
1657 uint32_t cur_validate_node)
1658{
1659 struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
1660
1661 if (likely(vmw_bo->on_validate_list))
1662 return vmw_bo->cur_validate_node;
1663
1664 vmw_bo->cur_validate_node = cur_validate_node;
1665 vmw_bo->on_validate_list = true;
1666
1667 return cur_validate_node;
1668}
1669
1670void vmw_dmabuf_validate_clear(struct ttm_buffer_object *bo)
1671{
1672 struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo);
1673
1674 vmw_bo->on_validate_list = false;
1675}
1676
1677int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile, 1732int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile,
1678 uint32_t handle, struct vmw_dma_buffer **out) 1733 uint32_t handle, struct vmw_dma_buffer **out)
1679{ 1734{
@@ -1702,6 +1757,18 @@ int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile,
1702 return 0; 1757 return 0;
1703} 1758}
1704 1759
1760int vmw_user_dmabuf_reference(struct ttm_object_file *tfile,
1761 struct vmw_dma_buffer *dma_buf)
1762{
1763 struct vmw_user_dma_buffer *user_bo;
1764
1765 if (dma_buf->base.destroy != vmw_user_dmabuf_destroy)
1766 return -EINVAL;
1767
1768 user_bo = container_of(dma_buf, struct vmw_user_dma_buffer, dma);
1769 return ttm_ref_object_add(tfile, &user_bo->base, TTM_REF_USAGE, NULL);
1770}
1771
1705/* 1772/*
1706 * Stream management 1773 * Stream management
1707 */ 1774 */
@@ -1726,8 +1793,8 @@ static int vmw_stream_init(struct vmw_private *dev_priv,
1726 struct vmw_resource *res = &stream->res; 1793 struct vmw_resource *res = &stream->res;
1727 int ret; 1794 int ret;
1728 1795
1729 ret = vmw_resource_init(dev_priv, res, &dev_priv->stream_idr, 1796 ret = vmw_resource_init(dev_priv, res, false, res_free,
1730 VMW_RES_STREAM, false, res_free, NULL); 1797 &vmw_stream_func);
1731 1798
1732 if (unlikely(ret != 0)) { 1799 if (unlikely(ret != 0)) {
1733 if (res_free == NULL) 1800 if (res_free == NULL)
@@ -1749,10 +1816,6 @@ static int vmw_stream_init(struct vmw_private *dev_priv,
1749 return 0; 1816 return 0;
1750} 1817}
1751 1818
1752/**
1753 * User-space context management:
1754 */
1755
1756static void vmw_user_stream_free(struct vmw_resource *res) 1819static void vmw_user_stream_free(struct vmw_resource *res)
1757{ 1820{
1758 struct vmw_user_stream *stream = 1821 struct vmw_user_stream *stream =
@@ -1788,9 +1851,11 @@ int vmw_stream_unref_ioctl(struct drm_device *dev, void *data,
1788 struct vmw_user_stream *stream; 1851 struct vmw_user_stream *stream;
1789 struct drm_vmw_stream_arg *arg = (struct drm_vmw_stream_arg *)data; 1852 struct drm_vmw_stream_arg *arg = (struct drm_vmw_stream_arg *)data;
1790 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 1853 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
1854 struct idr *idr = &dev_priv->res_idr[vmw_res_stream];
1791 int ret = 0; 1855 int ret = 0;
1792 1856
1793 res = vmw_resource_lookup(dev_priv, &dev_priv->stream_idr, arg->stream_id); 1857
1858 res = vmw_resource_lookup(dev_priv, idr, arg->stream_id);
1794 if (unlikely(res == NULL)) 1859 if (unlikely(res == NULL))
1795 return -EINVAL; 1860 return -EINVAL;
1796 1861
@@ -1891,7 +1956,8 @@ int vmw_user_stream_lookup(struct vmw_private *dev_priv,
1891 struct vmw_resource *res; 1956 struct vmw_resource *res;
1892 int ret; 1957 int ret;
1893 1958
1894 res = vmw_resource_lookup(dev_priv, &dev_priv->stream_idr, *inout_id); 1959 res = vmw_resource_lookup(dev_priv, &dev_priv->res_idr[vmw_res_stream],
1960 *inout_id);
1895 if (unlikely(res == NULL)) 1961 if (unlikely(res == NULL))
1896 return -EINVAL; 1962 return -EINVAL;
1897 1963
@@ -1986,3 +2052,453 @@ int vmw_dumb_destroy(struct drm_file *file_priv,
1986 return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, 2052 return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
1987 handle, TTM_REF_USAGE); 2053 handle, TTM_REF_USAGE);
1988} 2054}
2055
2056/**
2057 * vmw_resource_buf_alloc - Allocate a backup buffer for a resource.
2058 *
2059 * @res: The resource for which to allocate a backup buffer.
2060 * @interruptible: Whether any sleeps during allocation should be
2061 * performed while interruptible.
2062 */
2063static int vmw_resource_buf_alloc(struct vmw_resource *res,
2064 bool interruptible)
2065{
2066 unsigned long size =
2067 (res->backup_size + PAGE_SIZE - 1) & PAGE_MASK;
2068 struct vmw_dma_buffer *backup;
2069 int ret;
2070
2071 if (likely(res->backup)) {
2072 BUG_ON(res->backup->base.num_pages * PAGE_SIZE < size);
2073 return 0;
2074 }
2075
2076 backup = kzalloc(sizeof(*backup), GFP_KERNEL);
2077 if (unlikely(backup == NULL))
2078 return -ENOMEM;
2079
2080 ret = vmw_dmabuf_init(res->dev_priv, backup, res->backup_size,
2081 res->func->backup_placement,
2082 interruptible,
2083 &vmw_dmabuf_bo_free);
2084 if (unlikely(ret != 0))
2085 goto out_no_dmabuf;
2086
2087 res->backup = backup;
2088
2089out_no_dmabuf:
2090 return ret;
2091}
2092
2093/**
2094 * vmw_resource_do_validate - Make a resource up-to-date and visible
2095 * to the device.
2096 *
2097 * @res: The resource to make visible to the device.
2098 * @val_buf: Information about a buffer possibly
2099 * containing backup data if a bind operation is needed.
2100 *
2101 * On hardware resource shortage, this function returns -EBUSY and
2102 * should be retried once resources have been freed up.
2103 */
2104static int vmw_resource_do_validate(struct vmw_resource *res,
2105 struct ttm_validate_buffer *val_buf)
2106{
2107 int ret = 0;
2108 const struct vmw_res_func *func = res->func;
2109
2110 if (unlikely(res->id == -1)) {
2111 ret = func->create(res);
2112 if (unlikely(ret != 0))
2113 return ret;
2114 }
2115
2116 if (func->bind &&
2117 ((func->needs_backup && list_empty(&res->mob_head) &&
2118 val_buf->bo != NULL) ||
2119 (!func->needs_backup && val_buf->bo != NULL))) {
2120 ret = func->bind(res, val_buf);
2121 if (unlikely(ret != 0))
2122 goto out_bind_failed;
2123 if (func->needs_backup)
2124 list_add_tail(&res->mob_head, &res->backup->res_list);
2125 }
2126
2127 /*
2128 * Only do this on write operations, and move to
2129 * vmw_resource_unreserve if it can be called after
2130 * backup buffers have been unreserved. Otherwise
2131 * sort out locking.
2132 */
2133 res->res_dirty = true;
2134
2135 return 0;
2136
2137out_bind_failed:
2138 func->destroy(res);
2139
2140 return ret;
2141}
2142
2143/**
2144 * vmw_resource_unreserve - Unreserve a resource previously reserved for
2145 * command submission.
2146 *
2147 * @res: Pointer to the struct vmw_resource to unreserve.
2148 * @new_backup: Pointer to new backup buffer if command submission
2149 * switched.
2150 * @new_backup_offset: New backup offset if @new_backup is !NULL.
2151 *
2152 * Currently unreserving a resource means putting it back on the device's
2153 * resource lru list, so that it can be evicted if necessary.
2154 */
2155void vmw_resource_unreserve(struct vmw_resource *res,
2156 struct vmw_dma_buffer *new_backup,
2157 unsigned long new_backup_offset)
2158{
2159 struct vmw_private *dev_priv = res->dev_priv;
2160
2161 if (!list_empty(&res->lru_head))
2162 return;
2163
2164 if (new_backup && new_backup != res->backup) {
2165
2166 if (res->backup) {
2167 BUG_ON(atomic_read(&res->backup->base.reserved) == 0);
2168 list_del_init(&res->mob_head);
2169 vmw_dmabuf_unreference(&res->backup);
2170 }
2171
2172 res->backup = vmw_dmabuf_reference(new_backup);
2173 BUG_ON(atomic_read(&new_backup->base.reserved) == 0);
2174 list_add_tail(&res->mob_head, &new_backup->res_list);
2175 }
2176 if (new_backup)
2177 res->backup_offset = new_backup_offset;
2178
2179 if (!res->func->may_evict)
2180 return;
2181
2182 write_lock(&dev_priv->resource_lock);
2183 list_add_tail(&res->lru_head,
2184 &res->dev_priv->res_lru[res->func->res_type]);
2185 write_unlock(&dev_priv->resource_lock);
2186}
2187
2188/**
2189 * vmw_resource_check_buffer - Check whether a backup buffer is needed
2190 * for a resource and in that case, allocate
2191 * one, reserve and validate it.
2192 *
2193 * @res: The resource for which to allocate a backup buffer.
2194 * @interruptible: Whether any sleeps during allocation should be
2195 * performed while interruptible.
2196 * @val_buf: On successful return contains data about the
2197 * reserved and validated backup buffer.
2198 */
2199int vmw_resource_check_buffer(struct vmw_resource *res,
2200 bool interruptible,
2201 struct ttm_validate_buffer *val_buf)
2202{
2203 struct list_head val_list;
2204 bool backup_dirty = false;
2205 int ret;
2206
2207 if (unlikely(res->backup == NULL)) {
2208 ret = vmw_resource_buf_alloc(res, interruptible);
2209 if (unlikely(ret != 0))
2210 return ret;
2211 }
2212
2213 INIT_LIST_HEAD(&val_list);
2214 val_buf->bo = ttm_bo_reference(&res->backup->base);
2215 list_add_tail(&val_buf->head, &val_list);
2216 ret = ttm_eu_reserve_buffers(&val_list);
2217 if (unlikely(ret != 0))
2218 goto out_no_reserve;
2219
2220 if (res->func->needs_backup && list_empty(&res->mob_head))
2221 return 0;
2222
2223 backup_dirty = res->backup_dirty;
2224 ret = ttm_bo_validate(&res->backup->base,
2225 res->func->backup_placement,
2226 true, false, false);
2227
2228 if (unlikely(ret != 0))
2229 goto out_no_validate;
2230
2231 return 0;
2232
2233out_no_validate:
2234 ttm_eu_backoff_reservation(&val_list);
2235out_no_reserve:
2236 ttm_bo_unref(&val_buf->bo);
2237 if (backup_dirty)
2238 vmw_dmabuf_unreference(&res->backup);
2239
2240 return ret;
2241}
2242
2243/**
2244 * vmw_resource_reserve - Reserve a resource for command submission
2245 *
2246 * @res: The resource to reserve.
2247 *
2248 * This function takes the resource off the LRU list and make sure
2249 * a backup buffer is present for guest-backed resources. However,
2250 * the buffer may not be bound to the resource at this point.
2251 *
2252 */
2253int vmw_resource_reserve(struct vmw_resource *res, bool no_backup)
2254{
2255 struct vmw_private *dev_priv = res->dev_priv;
2256 int ret;
2257
2258 write_lock(&dev_priv->resource_lock);
2259 list_del_init(&res->lru_head);
2260 write_unlock(&dev_priv->resource_lock);
2261
2262 if (res->func->needs_backup && res->backup == NULL &&
2263 !no_backup) {
2264 ret = vmw_resource_buf_alloc(res, true);
2265 if (unlikely(ret != 0))
2266 return ret;
2267 }
2268
2269 return 0;
2270}
2271
2272/**
2273 * vmw_resource_backoff_reservation - Unreserve and unreference a
2274 * backup buffer
2275 *.
2276 * @val_buf: Backup buffer information.
2277 */
2278void vmw_resource_backoff_reservation(struct ttm_validate_buffer *val_buf)
2279{
2280 struct list_head val_list;
2281
2282 if (likely(val_buf->bo == NULL))
2283 return;
2284
2285 INIT_LIST_HEAD(&val_list);
2286 list_add_tail(&val_buf->head, &val_list);
2287 ttm_eu_backoff_reservation(&val_list);
2288 ttm_bo_unref(&val_buf->bo);
2289}
2290
2291/**
2292 * vmw_resource_do_evict - Evict a resource, and transfer its data
2293 * to a backup buffer.
2294 *
2295 * @res: The resource to evict.
2296 */
2297int vmw_resource_do_evict(struct vmw_resource *res)
2298{
2299 struct ttm_validate_buffer val_buf;
2300 const struct vmw_res_func *func = res->func;
2301 int ret;
2302
2303 BUG_ON(!func->may_evict);
2304
2305 val_buf.bo = NULL;
2306 ret = vmw_resource_check_buffer(res, true, &val_buf);
2307 if (unlikely(ret != 0))
2308 return ret;
2309
2310 if (unlikely(func->unbind != NULL &&
2311 (!func->needs_backup || !list_empty(&res->mob_head)))) {
2312 ret = func->unbind(res, res->res_dirty, &val_buf);
2313 if (unlikely(ret != 0))
2314 goto out_no_unbind;
2315 list_del_init(&res->mob_head);
2316 }
2317 ret = func->destroy(res);
2318 res->backup_dirty = true;
2319 res->res_dirty = false;
2320out_no_unbind:
2321 vmw_resource_backoff_reservation(&val_buf);
2322
2323 return ret;
2324}
2325
2326
2327/**
2328 * vmw_resource_validate - Make a resource up-to-date and visible
2329 * to the device.
2330 *
2331 * @res: The resource to make visible to the device.
2332 *
2333 * On succesful return, any backup DMA buffer pointed to by @res->backup will
2334 * be reserved and validated.
2335 * On hardware resource shortage, this function will repeatedly evict
2336 * resources of the same type until the validation succeeds.
2337 */
2338int vmw_resource_validate(struct vmw_resource *res)
2339{
2340 int ret;
2341 struct vmw_resource *evict_res;
2342 struct vmw_private *dev_priv = res->dev_priv;
2343 struct list_head *lru_list = &dev_priv->res_lru[res->func->res_type];
2344 struct ttm_validate_buffer val_buf;
2345
2346 if (likely(!res->func->may_evict))
2347 return 0;
2348
2349 val_buf.bo = NULL;
2350 if (res->backup)
2351 val_buf.bo = &res->backup->base;
2352 do {
2353 ret = vmw_resource_do_validate(res, &val_buf);
2354 if (likely(ret != -EBUSY))
2355 break;
2356
2357 write_lock(&dev_priv->resource_lock);
2358 if (list_empty(lru_list) || !res->func->may_evict) {
2359 DRM_ERROR("Out of device device id entries "
2360 "for %s.\n", res->func->type_name);
2361 ret = -EBUSY;
2362 write_unlock(&dev_priv->resource_lock);
2363 break;
2364 }
2365
2366 evict_res = vmw_resource_reference
2367 (list_first_entry(lru_list, struct vmw_resource,
2368 lru_head));
2369 list_del_init(&evict_res->lru_head);
2370
2371 write_unlock(&dev_priv->resource_lock);
2372 vmw_resource_do_evict(evict_res);
2373 vmw_resource_unreference(&evict_res);
2374 } while (1);
2375
2376 if (unlikely(ret != 0))
2377 goto out_no_validate;
2378 else if (!res->func->needs_backup && res->backup) {
2379 list_del_init(&res->mob_head);
2380 vmw_dmabuf_unreference(&res->backup);
2381 }
2382
2383 return 0;
2384
2385out_no_validate:
2386 return ret;
2387}
2388
2389/**
2390 * vmw_fence_single_bo - Utility function to fence a single TTM buffer
2391 * object without unreserving it.
2392 *
2393 * @bo: Pointer to the struct ttm_buffer_object to fence.
2394 * @fence: Pointer to the fence. If NULL, this function will
2395 * insert a fence into the command stream..
2396 *
2397 * Contrary to the ttm_eu version of this function, it takes only
2398 * a single buffer object instead of a list, and it also doesn't
2399 * unreserve the buffer object, which needs to be done separately.
2400 */
2401void vmw_fence_single_bo(struct ttm_buffer_object *bo,
2402 struct vmw_fence_obj *fence)
2403{
2404 struct ttm_bo_device *bdev = bo->bdev;
2405 struct ttm_bo_driver *driver = bdev->driver;
2406 struct vmw_fence_obj *old_fence_obj;
2407 struct vmw_private *dev_priv =
2408 container_of(bdev, struct vmw_private, bdev);
2409
2410 if (fence == NULL)
2411 vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL);
2412 else
2413 driver->sync_obj_ref(fence);
2414
2415 spin_lock(&bdev->fence_lock);
2416
2417 old_fence_obj = bo->sync_obj;
2418 bo->sync_obj = fence;
2419
2420 spin_unlock(&bdev->fence_lock);
2421
2422 if (old_fence_obj)
2423 vmw_fence_obj_unreference(&old_fence_obj);
2424}
2425
2426/**
2427 * vmw_resource_move_notify - TTM move_notify_callback
2428 *
2429 * @bo: The TTM buffer object about to move.
2430 * @mem: The truct ttm_mem_reg indicating to what memory
2431 * region the move is taking place.
2432 *
2433 * For now does nothing.
2434 */
2435void vmw_resource_move_notify(struct ttm_buffer_object *bo,
2436 struct ttm_mem_reg *mem)
2437{
2438}
2439
2440/**
2441 * vmw_resource_needs_backup - Return whether a resource needs a backup buffer.
2442 *
2443 * @res: The resource being queried.
2444 */
2445bool vmw_resource_needs_backup(const struct vmw_resource *res)
2446{
2447 return res->func->needs_backup;
2448}
2449
2450/**
2451 * vmw_resource_evict_type - Evict all resources of a specific type
2452 *
2453 * @dev_priv: Pointer to a device private struct
2454 * @type: The resource type to evict
2455 *
2456 * To avoid thrashing starvation or as part of the hibernation sequence,
2457 * evict all evictable resources of a specific type.
2458 */
2459static void vmw_resource_evict_type(struct vmw_private *dev_priv,
2460 enum vmw_res_type type)
2461{
2462 struct list_head *lru_list = &dev_priv->res_lru[type];
2463 struct vmw_resource *evict_res;
2464
2465 do {
2466 write_lock(&dev_priv->resource_lock);
2467
2468 if (list_empty(lru_list))
2469 goto out_unlock;
2470
2471 evict_res = vmw_resource_reference(
2472 list_first_entry(lru_list, struct vmw_resource,
2473 lru_head));
2474 list_del_init(&evict_res->lru_head);
2475 write_unlock(&dev_priv->resource_lock);
2476 vmw_resource_do_evict(evict_res);
2477 vmw_resource_unreference(&evict_res);
2478 } while (1);
2479
2480out_unlock:
2481 write_unlock(&dev_priv->resource_lock);
2482}
2483
2484/**
2485 * vmw_resource_evict_all - Evict all evictable resources
2486 *
2487 * @dev_priv: Pointer to a device private struct
2488 *
2489 * To avoid thrashing starvation or as part of the hibernation sequence,
2490 * evict all evictable resources. In particular this means that all
2491 * guest-backed resources that are registered with the device are
2492 * evicted and the OTable becomes clean.
2493 */
2494void vmw_resource_evict_all(struct vmw_private *dev_priv)
2495{
2496 enum vmw_res_type type;
2497
2498 mutex_lock(&dev_priv->cmdbuf_mutex);
2499
2500 for (type = 0; type < vmw_res_max; ++type)
2501 vmw_resource_evict_type(dev_priv, type);
2502
2503 mutex_unlock(&dev_priv->cmdbuf_mutex);
2504}