Skip to content

Commit 73f0e18

Browse files
zackrkerneltoast
authored andcommitted
drm/vmwgfx: Abstract placement selection
Problem with explicit placement selection in vmwgfx is that by the time the buffer object needs to be validated the information about which placement was supposed to be used is lost. To workaround this the driver had a bunch of state in various places e.g. as_mob or cpu_blit to somehow convey the information on which placement was intended. Fix it properly by allowing the buffer objects to hold their preferred placement so it can be reused whenever needed. This makes the entire validation pipeline a lot easier both to understand and maintain. Signed-off-by: Zack Rusin <[email protected]> Reviewed-by: Martin Krastev <[email protected]> Reviewed-by: Maaz Mombasawala <[email protected]> Acked-by: Thomas Zimmermann <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent b4945bb commit 73f0e18

22 files changed

+312
-456
lines changed

drivers/gpu/drm/vmwgfx/vmwgfx_bo.c

Lines changed: 126 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,17 @@ int vmw_bo_pin_in_vram_or_gmr(struct vmw_private *dev_priv,
135135
goto out_unreserve;
136136
}
137137

138-
ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, &ctx);
138+
vmw_bo_placement_set(buf,
139+
VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM,
140+
VMW_BO_DOMAIN_GMR);
141+
ret = ttm_bo_validate(bo, &buf->placement, &ctx);
139142
if (likely(ret == 0) || ret == -ERESTARTSYS)
140143
goto out_unreserve;
141144

142-
ret = ttm_bo_validate(bo, &vmw_vram_placement, &ctx);
145+
vmw_bo_placement_set(buf,
146+
VMW_BO_DOMAIN_VRAM,
147+
VMW_BO_DOMAIN_VRAM);
148+
ret = ttm_bo_validate(bo, &buf->placement, &ctx);
143149

144150
out_unreserve:
145151
if (!ret)
@@ -190,17 +196,8 @@ int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv,
190196
{
191197
struct ttm_operation_ctx ctx = {interruptible, false };
192198
struct ttm_buffer_object *bo = &buf->base;
193-
struct ttm_placement placement;
194-
struct ttm_place place;
195199
int ret = 0;
196200

197-
place = vmw_vram_placement.placement[0];
198-
place.lpfn = bo->resource->num_pages;
199-
placement.num_placement = 1;
200-
placement.placement = &place;
201-
placement.num_busy_placement = 1;
202-
placement.busy_placement = &place;
203-
204201
vmw_execbuf_release_pinned_bo(dev_priv);
205202
ret = ttm_bo_reserve(bo, interruptible, false, NULL);
206203
if (unlikely(ret != 0))
@@ -216,14 +213,21 @@ int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv,
216213
bo->resource->start > 0 &&
217214
buf->base.pin_count == 0) {
218215
ctx.interruptible = false;
219-
(void) ttm_bo_validate(bo, &vmw_sys_placement, &ctx);
216+
vmw_bo_placement_set(buf,
217+
VMW_BO_DOMAIN_SYS,
218+
VMW_BO_DOMAIN_SYS);
219+
(void)ttm_bo_validate(bo, &buf->placement, &ctx);
220220
}
221221

222+
vmw_bo_placement_set(buf,
223+
VMW_BO_DOMAIN_VRAM,
224+
VMW_BO_DOMAIN_VRAM);
225+
buf->places[0].lpfn = bo->resource->num_pages;
222226
if (buf->base.pin_count > 0)
223-
ret = ttm_resource_compat(bo->resource, &placement)
227+
ret = ttm_resource_compat(bo->resource, &buf->placement)
224228
? 0 : -EINVAL;
225229
else
226-
ret = ttm_bo_validate(bo, &placement, &ctx);
230+
ret = ttm_bo_validate(bo, &buf->placement, &ctx);
227231

228232
/* For some reason we didn't end up at the start of vram */
229233
WARN_ON(ret == 0 && bo->resource->start != 0);
@@ -431,7 +435,7 @@ int vmw_bo_create_kernel(struct vmw_private *dev_priv, unsigned long size,
431435
}
432436

433437
int vmw_bo_create(struct vmw_private *vmw,
434-
size_t size, struct ttm_placement *placement,
438+
size_t size, u32 domain, u32 busy_domain,
435439
bool interruptible, bool pin,
436440
struct vmw_bo **p_bo)
437441
{
@@ -444,7 +448,8 @@ int vmw_bo_create(struct vmw_private *vmw,
444448
}
445449

446450
ret = vmw_bo_init(vmw, *p_bo, size,
447-
placement, interruptible, pin);
451+
domain, busy_domain,
452+
interruptible, pin);
448453
if (unlikely(ret != 0))
449454
goto out_error;
450455

@@ -461,7 +466,8 @@ int vmw_bo_create(struct vmw_private *vmw,
461466
* @dev_priv: Pointer to the device private struct
462467
* @vmw_bo: Pointer to the struct vmw_bo to initialize.
463468
* @size: Buffer object size in bytes.
464-
* @placement: Initial placement.
469+
* @domain: Domain to put the bo in.
470+
* @busy_domain: Domain to put the bo if busy.
465471
* @interruptible: Whether waits should be performed interruptible.
466472
* @pin: If the BO should be created pinned at a fixed location.
467473
* Returns: Zero on success, negative error code on error.
@@ -470,7 +476,9 @@ int vmw_bo_create(struct vmw_private *vmw,
470476
*/
471477
int vmw_bo_init(struct vmw_private *dev_priv,
472478
struct vmw_bo *vmw_bo,
473-
size_t size, struct ttm_placement *placement,
479+
size_t size,
480+
u32 domain,
481+
u32 busy_domain,
474482
bool interruptible, bool pin)
475483
{
476484
struct ttm_operation_ctx ctx = {
@@ -489,9 +497,10 @@ int vmw_bo_init(struct vmw_private *dev_priv,
489497
size = ALIGN(size, PAGE_SIZE);
490498
drm_gem_private_object_init(vdev, &vmw_bo->base.base, size);
491499

500+
vmw_bo_placement_set(vmw_bo, domain, busy_domain);
492501
ret = ttm_bo_init_reserved(bdev, &vmw_bo->base, size,
493502
ttm_bo_type_device,
494-
placement,
503+
&vmw_bo->placement,
495504
0, &ctx, NULL, NULL, vmw_bo_free);
496505
if (unlikely(ret)) {
497506
return ret;
@@ -815,3 +824,101 @@ void vmw_bo_move_notify(struct ttm_buffer_object *bo,
815824
if (mem->mem_type != VMW_PL_MOB && bo->resource->mem_type == VMW_PL_MOB)
816825
vmw_resource_unbind_list(vbo);
817826
}
827+
828+
static u32
829+
set_placement_list(struct ttm_place *pl, u32 domain)
830+
{
831+
u32 n = 0;
832+
833+
/*
834+
* The placements are ordered according to our preferences
835+
*/
836+
if (domain & VMW_BO_DOMAIN_MOB) {
837+
pl[n].mem_type = VMW_PL_MOB;
838+
pl[n].flags = 0;
839+
pl[n].fpfn = 0;
840+
pl[n].lpfn = 0;
841+
n++;
842+
}
843+
if (domain & VMW_BO_DOMAIN_GMR) {
844+
pl[n].mem_type = VMW_PL_GMR;
845+
pl[n].flags = 0;
846+
pl[n].fpfn = 0;
847+
pl[n].lpfn = 0;
848+
n++;
849+
}
850+
if (domain & VMW_BO_DOMAIN_VRAM) {
851+
pl[n].mem_type = TTM_PL_VRAM;
852+
pl[n].flags = 0;
853+
pl[n].fpfn = 0;
854+
pl[n].lpfn = 0;
855+
n++;
856+
}
857+
WARN_ON((domain & VMW_BO_DOMAIN_WAITABLE_SYS) != 0);
858+
if (domain & VMW_BO_DOMAIN_WAITABLE_SYS) {
859+
pl[n].mem_type = VMW_PL_SYSTEM;
860+
pl[n].flags = 0;
861+
pl[n].fpfn = 0;
862+
pl[n].lpfn = 0;
863+
n++;
864+
}
865+
if (domain & VMW_BO_DOMAIN_SYS) {
866+
pl[n].mem_type = TTM_PL_SYSTEM;
867+
pl[n].flags = 0;
868+
pl[n].fpfn = 0;
869+
pl[n].lpfn = 0;
870+
n++;
871+
}
872+
873+
WARN_ON(!n);
874+
if (!n) {
875+
pl[n].mem_type = TTM_PL_SYSTEM;
876+
pl[n].flags = 0;
877+
pl[n].fpfn = 0;
878+
pl[n].lpfn = 0;
879+
n++;
880+
}
881+
return n;
882+
}
883+
884+
void vmw_bo_placement_set(struct vmw_bo *bo, u32 domain, u32 busy_domain)
885+
{
886+
struct ttm_device *bdev = bo->base.bdev;
887+
struct vmw_private *vmw =
888+
container_of(bdev, struct vmw_private, bdev);
889+
struct ttm_placement *pl = &bo->placement;
890+
bool mem_compatible = false;
891+
u32 i;
892+
893+
pl->placement = bo->places;
894+
pl->num_placement = set_placement_list(bo->places, domain);
895+
896+
if (drm_debug_enabled(DRM_UT_DRIVER) && bo->base.resource) {
897+
for (i = 0; i < pl->num_placement; ++i) {
898+
if (bo->base.resource->mem_type == TTM_PL_SYSTEM ||
899+
bo->base.resource->mem_type == pl->placement[i].mem_type)
900+
mem_compatible = true;
901+
}
902+
if (!mem_compatible)
903+
drm_warn(&vmw->drm,
904+
"%s: Incompatible transition from "
905+
"bo->base.resource->mem_type = %u to domain = %u\n",
906+
__func__, bo->base.resource->mem_type, domain);
907+
}
908+
909+
pl->busy_placement = bo->busy_places;
910+
pl->num_busy_placement = set_placement_list(bo->busy_places, busy_domain);
911+
}
912+
913+
void vmw_bo_placement_set_default_accelerated(struct vmw_bo *bo)
914+
{
915+
struct ttm_device *bdev = bo->base.bdev;
916+
struct vmw_private *vmw =
917+
container_of(bdev, struct vmw_private, bdev);
918+
u32 domain = VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM;
919+
920+
if (vmw->has_mob)
921+
domain = VMW_BO_DOMAIN_MOB;
922+
923+
vmw_bo_placement_set(bo, domain, domain);
924+
}

drivers/gpu/drm/vmwgfx/vmwgfx_bo.h

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "device_include/svga_reg.h"
3232

3333
#include <drm/ttm/ttm_bo.h>
34+
#include <drm/ttm/ttm_placement.h>
3435

3536
#include <linux/rbtree_types.h>
3637
#include <linux/types.h>
@@ -40,6 +41,14 @@ struct vmw_fence_obj;
4041
struct vmw_private;
4142
struct vmw_resource;
4243

44+
enum vmw_bo_domain {
45+
VMW_BO_DOMAIN_SYS = BIT(0),
46+
VMW_BO_DOMAIN_WAITABLE_SYS = BIT(1),
47+
VMW_BO_DOMAIN_VRAM = BIT(2),
48+
VMW_BO_DOMAIN_GMR = BIT(3),
49+
VMW_BO_DOMAIN_MOB = BIT(4),
50+
};
51+
4352
/**
4453
* struct vmw_bo - TTM buffer object with vmwgfx additions
4554
* @base: The TTM buffer object
@@ -54,6 +63,11 @@ struct vmw_resource;
5463
*/
5564
struct vmw_bo {
5665
struct ttm_buffer_object base;
66+
67+
struct ttm_placement placement;
68+
struct ttm_place places[5];
69+
struct ttm_place busy_places[5];
70+
5771
struct rb_root res_tree;
5872
/* For KMS atomic helpers: ttm bo mapping count */
5973
atomic_t base_mapped_count;
@@ -67,17 +81,24 @@ struct vmw_bo {
6781
struct vmw_bo_dirty *dirty;
6882
};
6983

84+
void vmw_bo_placement_set(struct vmw_bo *bo, u32 domain, u32 busy_domain);
85+
void vmw_bo_placement_set_default_accelerated(struct vmw_bo *bo);
86+
7087
int vmw_bo_create_kernel(struct vmw_private *dev_priv,
7188
unsigned long size,
7289
struct ttm_placement *placement,
7390
struct ttm_buffer_object **p_bo);
7491
int vmw_bo_create(struct vmw_private *dev_priv,
75-
size_t size, struct ttm_placement *placement,
92+
size_t size,
93+
u32 domain,
94+
u32 busy_domain,
7695
bool interruptible, bool pin,
7796
struct vmw_bo **p_bo);
7897
int vmw_bo_init(struct vmw_private *dev_priv,
7998
struct vmw_bo *vmw_bo,
80-
size_t size, struct ttm_placement *placement,
99+
size_t size,
100+
u32 domain,
101+
u32 busy_domain,
81102
bool interruptible, bool pin);
82103
int vmw_bo_unref_ioctl(struct drm_device *dev, void *data,
83104
struct drm_file *file_priv);

drivers/gpu/drm/vmwgfx/vmwgfx_context.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ static const struct vmw_res_func vmw_legacy_context_func = {
7676
.needs_backup = false,
7777
.may_evict = false,
7878
.type_name = "legacy contexts",
79-
.backup_placement = NULL,
79+
.domain = VMW_BO_DOMAIN_SYS,
80+
.busy_domain = VMW_BO_DOMAIN_SYS,
8081
.create = NULL,
8182
.destroy = NULL,
8283
.bind = NULL,
@@ -90,7 +91,8 @@ static const struct vmw_res_func vmw_gb_context_func = {
9091
.prio = 3,
9192
.dirty_prio = 3,
9293
.type_name = "guest backed contexts",
93-
.backup_placement = &vmw_mob_placement,
94+
.domain = VMW_BO_DOMAIN_MOB,
95+
.busy_domain = VMW_BO_DOMAIN_MOB,
9496
.create = vmw_gb_context_create,
9597
.destroy = vmw_gb_context_destroy,
9698
.bind = vmw_gb_context_bind,
@@ -104,7 +106,8 @@ static const struct vmw_res_func vmw_dx_context_func = {
104106
.prio = 3,
105107
.dirty_prio = 3,
106108
.type_name = "dx contexts",
107-
.backup_placement = &vmw_mob_placement,
109+
.domain = VMW_BO_DOMAIN_MOB,
110+
.busy_domain = VMW_BO_DOMAIN_MOB,
108111
.create = vmw_dx_context_create,
109112
.destroy = vmw_dx_context_destroy,
110113
.bind = vmw_dx_context_bind,

drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ static const struct vmw_res_func vmw_cotable_func = {
123123
.prio = 3,
124124
.dirty_prio = 3,
125125
.type_name = "context guest backed object tables",
126-
.backup_placement = &vmw_mob_placement,
126+
.domain = VMW_BO_DOMAIN_MOB,
127+
.busy_domain = VMW_BO_DOMAIN_MOB,
127128
.create = vmw_cotable_create,
128129
.destroy = vmw_cotable_destroy,
129130
.bind = vmw_cotable_bind,
@@ -408,7 +409,8 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size)
408409
* for the new COTable. Initially pin the buffer object to make sure
409410
* we can use tryreserve without failure.
410411
*/
411-
ret = vmw_bo_create(dev_priv, new_size, &vmw_mob_placement,
412+
ret = vmw_bo_create(dev_priv, new_size,
413+
VMW_BO_DOMAIN_MOB, VMW_BO_DOMAIN_MOB,
412414
true, true, &buf);
413415
if (ret) {
414416
DRM_ERROR("Failed initializing new cotable MOB.\n");
@@ -449,7 +451,10 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size)
449451
}
450452

451453
/* Unpin new buffer, and switch backup buffers. */
452-
ret = ttm_bo_validate(bo, &vmw_mob_placement, &ctx);
454+
vmw_bo_placement_set(buf,
455+
VMW_BO_DOMAIN_MOB,
456+
VMW_BO_DOMAIN_MOB);
457+
ret = ttm_bo_validate(bo, &buf->placement, &ctx);
453458
if (unlikely(ret != 0)) {
454459
DRM_ERROR("Failed validating new COTable backup buffer.\n");
455460
goto out_wait;

drivers/gpu/drm/vmwgfx/vmwgfx_drv.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,8 @@ static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv)
401401
* user of the bo currently.
402402
*/
403403
ret = vmw_bo_create(dev_priv, PAGE_SIZE,
404-
&vmw_sys_placement, false, true, &vbo);
404+
VMW_BO_DOMAIN_SYS, VMW_BO_DOMAIN_SYS,
405+
false, true, &vbo);
405406
if (unlikely(ret != 0))
406407
return ret;
407408

drivers/gpu/drm/vmwgfx/vmwgfx_drv.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -927,9 +927,7 @@ extern struct ttm_placement vmw_vram_placement;
927927
extern struct ttm_placement vmw_vram_sys_placement;
928928
extern struct ttm_placement vmw_vram_gmr_placement;
929929
extern struct ttm_placement vmw_sys_placement;
930-
extern struct ttm_placement vmw_srf_placement;
931930
extern struct ttm_placement vmw_mob_placement;
932-
extern struct ttm_placement vmw_nonfixed_placement;
933931
extern struct ttm_device_funcs vmw_bo_driver;
934932
extern const struct vmw_sg_table *
935933
vmw_bo_sg_table(struct ttm_buffer_object *bo);

0 commit comments

Comments
 (0)