summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-05-30 18:30:47 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2014-05-30 23:49:27 +0100
commit40fe1f2c09a98ac75b05db3663d29ee1a64ed280 (patch)
treec7dc046d257e312240a058e7cd186cbba236573d
parentfc1f9b91ae2c761e4b126daecab13e13ae2534d3 (diff)
sna: Do not allow imported buffers to be cached
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/kgem.c108
-rw-r--r--src/sna/kgem.h1
-rw-r--r--src/sna/sna_display.c3
3 files changed, 63 insertions, 49 deletions
diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 4b7bc648..44c7622d 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -1758,6 +1758,17 @@ static void kgem_bo_binding_free(struct kgem *kgem, struct kgem_bo *bo)
}
}
+static void kgem_bo_rmfb(struct kgem *kgem, struct kgem_bo *bo)
+{
+ if (bo->scanout && bo->delta) {
+ DBG(("%s: releasing fb=%d for handle=%d\n",
+ __FUNCTION__, bo->delta, bo->handle));
+ /* XXX will leak if we are not DRM_MASTER. *shrug* */
+ do_ioctl(kgem->fd, DRM_IOCTL_MODE_RMFB, &bo->delta);
+ bo->delta = 0;
+ }
+}
+
static void kgem_bo_free(struct kgem *kgem, struct kgem_bo *bo)
{
DBG(("%s: handle=%d, size=%d\n", __FUNCTION__, bo->handle, bytes(bo)));
@@ -1772,6 +1783,7 @@ static void kgem_bo_free(struct kgem *kgem, struct kgem_bo *bo)
#endif
kgem_bo_binding_free(kgem, bo);
+ kgem_bo_rmfb(kgem, bo);
if (IS_USER_MAP(bo->map__cpu)) {
assert(bo->rq == NULL);
@@ -1960,7 +1972,6 @@ static void kgem_bo_move_to_scanout(struct kgem *kgem, struct kgem_bo *bo)
{
assert(bo->refcnt == 0);
assert(bo->scanout);
- assert(bo->delta);
assert(!bo->flush);
assert(!bo->snoop);
assert(!bo->io);
@@ -1988,6 +1999,7 @@ static void kgem_bo_move_to_scanout(struct kgem *kgem, struct kgem_bo *bo)
static void kgem_bo_move_to_snoop(struct kgem *kgem, struct kgem_bo *bo)
{
assert(bo->reusable);
+ assert(!bo->scanout);
assert(!bo->flush);
assert(!bo->needs_flush);
assert(bo->refcnt == 0);
@@ -2008,6 +2020,30 @@ static void kgem_bo_move_to_snoop(struct kgem *kgem, struct kgem_bo *bo)
kgem->need_expire = true;
}
+static bool kgem_bo_move_to_cache(struct kgem *kgem, struct kgem_bo *bo)
+{
+ bool retired = false;
+
+ DBG(("%s: release handle=%d\n", __FUNCTION__, bo->handle));
+
+ if (bo->prime) {
+ DBG(("%s: discarding imported prime handle=%d\n",
+ __FUNCTION__, bo->handle));
+ kgem_bo_free(kgem, bo);
+ } else if (bo->snoop) {
+ kgem_bo_move_to_snoop(kgem, bo);
+ } else if (bo->scanout) {
+ kgem_bo_move_to_scanout(kgem, bo);
+ } else if ((bo = kgem_bo_replace_io(bo))->reusable &&
+ kgem_bo_set_purgeable(kgem, bo)) {
+ kgem_bo_move_to_inactive(kgem, bo);
+ retired = true;
+ } else
+ kgem_bo_free(kgem, bo);
+
+ return retired;
+}
+
static struct kgem_bo *
search_snoop_cache(struct kgem *kgem, unsigned int num_pages, unsigned flags)
{
@@ -2103,6 +2139,9 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
if (DBG_NO_CACHE)
goto destroy;
+ if (bo->prime)
+ goto destroy;
+
if (bo->snoop && !bo->flush) {
DBG(("%s: handle=%d is snooped\n", __FUNCTION__, bo->handle));
assert(bo->reusable);
@@ -2116,7 +2155,7 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
if (!IS_USER_MAP(bo->map__cpu))
bo->flush = false;
- if (bo->scanout && bo->delta) {
+ if (bo->scanout) {
kgem_bo_move_to_scanout(kgem, bo);
return;
}
@@ -2227,16 +2266,7 @@ static bool kgem_retire__flushing(struct kgem *kgem)
if (bo->refcnt)
continue;
- if (bo->snoop) {
- kgem_bo_move_to_snoop(kgem, bo);
- } else if (bo->scanout && bo->delta) {
- kgem_bo_move_to_scanout(kgem, bo);
- } else if ((bo = kgem_bo_replace_io(bo))->reusable &&
- kgem_bo_set_purgeable(kgem, bo)) {
- kgem_bo_move_to_inactive(kgem, bo);
- retired = true;
- } else
- kgem_bo_free(kgem, bo);
+ retired |= kgem_bo_move_to_cache(kgem, bo);
}
#if HAS_DEBUG_FULL
{
@@ -2289,19 +2319,7 @@ static bool __kgem_retire_rq(struct kgem *kgem, struct kgem_request *rq)
if (bo->refcnt)
continue;
- if (bo->snoop) {
- kgem_bo_move_to_snoop(kgem, bo);
- } else if (bo->scanout && bo->delta) {
- kgem_bo_move_to_scanout(kgem, bo);
- } else if ((bo = kgem_bo_replace_io(bo))->reusable &&
- kgem_bo_set_purgeable(kgem, bo)) {
- kgem_bo_move_to_inactive(kgem, bo);
- retired = true;
- } else {
- DBG(("%s: closing %d\n",
- __FUNCTION__, bo->handle));
- kgem_bo_free(kgem, bo);
- }
+ retired |= kgem_bo_move_to_cache(kgem, bo);
}
assert(rq->bo->rq == NULL);
@@ -2827,18 +2845,7 @@ void kgem_reset(struct kgem *kgem)
if (bo->refcnt || bo->rq)
continue;
- if (bo->snoop) {
- kgem_bo_move_to_snoop(kgem, bo);
- } else if (bo->scanout && bo->delta) {
- kgem_bo_move_to_scanout(kgem, bo);
- } else if ((bo = kgem_bo_replace_io(bo))->reusable &&
- kgem_bo_set_purgeable(kgem, bo)) {
- kgem_bo_move_to_inactive(kgem, bo);
- } else {
- DBG(("%s: closing %d\n",
- __FUNCTION__, bo->handle));
- kgem_bo_free(kgem, bo);
- }
+ kgem_bo_move_to_cache(kgem, bo);
}
if (rq != &kgem->static_request) {
@@ -3273,8 +3280,8 @@ void kgem_clean_scanout_cache(struct kgem *kgem)
bo = list_first_entry(&kgem->scanout, struct kgem_bo, list);
assert(bo->scanout);
- assert(bo->delta);
assert(!bo->refcnt);
+ assert(!bo->prime);
assert(bo->proxy == NULL);
if (bo->exec || __kgem_busy(kgem, bo->handle))
@@ -3284,9 +3291,7 @@ void kgem_clean_scanout_cache(struct kgem *kgem)
__FUNCTION__, bo->handle, bo->delta, bo->reusable));
list_del(&bo->list);
- /* XXX will leak if we are not DRM_MASTER. *shrug* */
- do_ioctl(kgem->fd, DRM_IOCTL_MODE_RMFB, &bo->delta);
- bo->delta = 0;
+ kgem_bo_rmfb(kgem, bo);
bo->scanout = false;
if (!bo->purged) {
@@ -3800,7 +3805,7 @@ struct kgem_bo *kgem_create_for_name(struct kgem *kgem, uint32_t name)
bo->unique_id = kgem_get_unique_id(kgem);
bo->tiling = tiling.tiling_mode;
bo->reusable = false;
- bo->flush = true;
+ bo->prime = true;
bo->purged = true; /* no coherency guarantees */
debug_alloc__bo(kgem, bo);
@@ -3850,6 +3855,7 @@ struct kgem_bo *kgem_create_for_prime(struct kgem *kgem, int name, uint32_t size
bo->unique_id = kgem_get_unique_id(kgem);
bo->tiling = tiling.tiling_mode;
bo->reusable = false;
+ bo->prime = true;
bo->domain = DOMAIN_NONE;
/* is this a special bo (e.g. scanout or CPU coherent)? */
@@ -4225,10 +4231,8 @@ static void __kgem_bo_make_scanout(struct kgem *kgem,
arg.depth = scrn->depth;
arg.handle = bo->handle;
- if (gem_set_caching(kgem->fd, bo->handle, DISPLAY) &&
- do_ioctl(kgem->fd, DRM_IOCTL_MODE_ADDFB, &arg) == 0) {
+ if (gem_set_caching(kgem->fd, bo->handle, DISPLAY)) {
bo->scanout = true;
- bo->delta = arg.fb_id;
/* Pre-emptively move the object into the mappable
* portion to avoid rebinding later when busy.
@@ -4240,6 +4244,12 @@ static void __kgem_bo_make_scanout(struct kgem *kgem,
bo->domain = DOMAIN_GTT;
}
}
+
+ if (do_ioctl(kgem->fd, DRM_IOCTL_MODE_ADDFB, &arg) == 0) {
+ DBG(("%s: attached fb=%d to handle=%d\n",
+ __FUNCTION__, arg.fb_id, arg.handle));
+ bo->delta = arg.fb_id;
+ }
}
struct kgem_bo *kgem_create_2d(struct kgem *kgem,
@@ -4281,7 +4291,6 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
list_for_each_entry_reverse(bo, &kgem->scanout, list) {
assert(bo->scanout);
- assert(bo->delta);
assert(!bo->flush);
assert_tiling(kgem, bo);
@@ -4292,7 +4301,7 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
/* No tiling/pitch without recreating fb */
continue;
- if (!check_scanout_size(kgem, bo, width, height)) {
+ if (bo->delta && !check_scanout_size(kgem, bo, width, height)) {
if (first == NULL)
first = bo;
continue;
@@ -4354,11 +4363,12 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
arg.depth = scrn->depth;
arg.handle = bo->handle;
- do_ioctl(kgem->fd, DRM_IOCTL_MODE_RMFB, &bo->delta);
+ kgem_bo_rmfb(kgem, bo);
if (do_ioctl(kgem->fd, DRM_IOCTL_MODE_ADDFB, &arg)) {
- bo->scanout = false;
kgem_bo_free(kgem, bo);
} else {
+ DBG(("%s: attached fb=%d to handle=%d\n",
+ __FUNCTION__, arg.fb_id, arg.handle));
bo->delta = arg.fb_id;
return bo;
}
diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index dbc5ddbd..12a99dba 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -95,6 +95,7 @@ struct kgem_bo {
uint32_t io : 1;
uint32_t flush : 1;
uint32_t scanout : 1;
+ uint32_t prime : 1;
uint32_t purged : 1;
};
#define DOMAIN_NONE 0
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 39806502..1761be60 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -339,6 +339,9 @@ static unsigned get_fb(struct sna *sna, struct kgem_bo *bo,
}
assert(arg.fb_id != 0);
+ DBG(("%s: attached fb=%d to handle=%d\n",
+ __FUNCTION__, arg.fb_id, arg.handle));
+
bo->scanout = true;
return bo->delta = arg.fb_id;
}