summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-06-09 01:03:16 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2011-06-09 09:45:13 +0100
commit4d509d501b09f565fea232947e6f53d54a08749f (patch)
tree94cc595e04ac6ab9406a5accfb0d53d64a741c98
parent17be5e2eb41b2ada94954b87c855961003c2fc7c (diff)
sna: Tweak retiring old bo
As we check for retirement everytime we wakeup, it is seldom useful to check again until we know we have invoked an operation that may block. But when we do check, we do not want to scan the entire active list looking for flushing candidates, so track those on a separate list. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/kgem.c50
-rw-r--r--src/sna/kgem.h12
-rw-r--r--src/sna/sna_accel.c2
3 files changed, 33 insertions, 31 deletions
diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 979a5525..1c88e7f6 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -158,7 +158,8 @@ Bool kgem_bo_write(struct kgem *kgem, struct kgem_bo *bo,
if (gem_write(kgem->fd, bo->handle, 0, length, data))
return FALSE;
- _kgem_retire(kgem);
+ if (bo->gpu)
+ kgem_retire(kgem);
return TRUE;
}
@@ -292,6 +293,7 @@ void kgem_init(struct kgem *kgem, int fd, int gen)
list_init(&kgem->partial);
list_init(&kgem->requests);
list_init(&kgem->active);
+ list_init(&kgem->flushing);
for (i = 0; i < ARRAY_SIZE(kgem->inactive); i++)
list_init(&kgem->inactive[i]);
@@ -500,6 +502,11 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
}
list_move(&bo->list, (bo->rq || bo->needs_flush) ? &kgem->active : inactive(kgem, bo->size));
+ if (bo->rq == NULL && bo->needs_flush) {
+ assert(list_is_empty(&bo->request));
+ list_add(&bo->request, &kgem->flushing);
+ }
+
return;
destroy:
@@ -516,16 +523,19 @@ static void kgem_bo_unref(struct kgem *kgem, struct kgem_bo *bo)
__kgem_bo_destroy(kgem, bo);
}
-void _kgem_retire(struct kgem *kgem)
+void kgem_retire(struct kgem *kgem)
{
struct kgem_bo *bo, *next;
- list_for_each_entry_safe(bo, next, &kgem->active, list) {
- if (bo->rq == NULL && !kgem_busy(kgem, bo->handle)) {
+ list_for_each_entry_safe(bo, next, &kgem->flushing, request) {
+ if (!kgem_busy(kgem, bo->handle)) {
+ assert(bo->rq == NULL);
assert(bo->needs_flush);
assert(bo->deleted);
bo->needs_flush = 0;
+ bo->gpu = false;
list_move(&bo->list, inactive(kgem, bo->size));
+ list_del(&bo->request);
}
}
@@ -544,11 +554,13 @@ void _kgem_retire(struct kgem *kgem)
request);
list_del(&bo->request);
bo->rq = NULL;
- bo->gpu = false;
- if (bo->refcnt == 0 && !bo->needs_flush) {
+ if (bo->refcnt == 0) {
assert(bo->deleted);
- if (bo->reusable) {
+ if (bo->needs_flush) {
+ list_add(&bo->request, &kgem->flushing);
+ } else if (bo->reusable) {
+ bo->gpu = false;
list_move(&bo->list,
inactive(kgem, bo->size));
} else {
@@ -573,8 +585,6 @@ void _kgem_retire(struct kgem *kgem)
list_del(&rq->list);
free(rq);
}
-
- kgem->retire = 0;
}
static void kgem_commit(struct kgem *kgem)
@@ -897,8 +907,6 @@ void _kgem_submit(struct kgem *kgem)
kgem->mode = KGEM_NONE;
kgem->flush = 0;
- kgem->retire = 1;
-
sna_kgem_reset(kgem);
}
@@ -930,7 +938,7 @@ bool kgem_expire_cache(struct kgem *kgem)
bool idle;
int i;
- _kgem_retire(kgem);
+ kgem_retire(kgem);
if (kgem->wedged)
kgem_cleanup(kgem);
@@ -994,12 +1002,7 @@ search_linear_cache(struct kgem *kgem, int size, bool active)
struct kgem_bo *bo, *next;
struct list *cache;
- if (!active) {
- cache = inactive(kgem, size);
- kgem_retire(kgem);
- } else
- cache = &kgem->active;
-
+ cache = active ? &kgem->active : inactive(kgem, size);
list_for_each_entry_safe(bo, next, cache, list) {
if (size > bo->size)
continue;
@@ -1008,6 +1011,8 @@ search_linear_cache(struct kgem *kgem, int size, bool active)
continue;
list_del(&bo->list);
+ if (bo->rq == NULL)
+ list_del(&bo->request);
if (bo->deleted) {
if (!gem_madvise(kgem->fd, bo->handle,
@@ -1245,6 +1250,8 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
}
list_del(&bo->list);
+ if (bo->rq == NULL)
+ list_del(&bo->request);
if (bo->deleted) {
if (!gem_madvise(kgem->fd, bo->handle,
@@ -1293,6 +1300,7 @@ skip_active_search:
bo->tiling = tiling;
list_del(&bo->list);
+ assert(list_is_empty(&bo->request));
if (bo->deleted) {
if (!gem_madvise(kgem->fd, bo->handle,
@@ -1571,7 +1579,8 @@ void kgem_bo_sync(struct kgem *kgem, struct kgem_bo *bo, bool for_write)
set_domain.write_domain = for_write ? I915_GEM_DOMAIN_CPU : 0;
drmIoctl(kgem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
- _kgem_retire(kgem);
+ if (bo->gpu)
+ kgem_retire(kgem);
bo->cpu_read = true;
if (for_write)
bo->cpu_write = true;
@@ -1767,7 +1776,8 @@ void kgem_buffer_sync(struct kgem *kgem, struct kgem_bo *_bo)
0, bo->used, bo+1);
else
gem_read(kgem->fd, bo->base.handle, bo+1, bo->used);
- _kgem_retire(kgem);
+ if (bo->base.gpu)
+ kgem_retire(kgem);
bo->need_io = 0;
}
diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index 37803bdf..2b05c12d 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -86,8 +86,7 @@ struct kgem {
KGEM_BLT,
} mode, ring;
- struct list active;
- struct list inactive[16];
+ struct list active, flushing, inactive[16];
struct list partial;
struct list requests;
struct kgem_request *next_request;
@@ -98,7 +97,6 @@ struct kgem {
uint16_t nreloc;
uint16_t nfence;
- uint32_t retire;
uint32_t flush;
uint32_t need_purge;
@@ -155,12 +153,7 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
int tiling,
uint32_t flags);
-void _kgem_retire(struct kgem *kgem);
-static inline void kgem_retire(struct kgem *kgem)
-{
- if (kgem->retire)
- _kgem_retire(kgem);
-}
+void kgem_retire(struct kgem *kgem);
void _kgem_submit(struct kgem *kgem);
static inline void kgem_submit(struct kgem *kgem)
@@ -290,7 +283,6 @@ static inline bool kgem_bo_is_busy(struct kgem *kgem, struct kgem_bo *bo)
if (!bo->gpu)
return false;
- kgem_retire(kgem);
return bo->rq != NULL;
}
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 82c99732..1ddfe524 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -3306,7 +3306,7 @@ void sna_accel_block_handler(struct sna *sna)
void sna_accel_wakeup_handler(struct sna *sna)
{
- _kgem_retire(&sna->kgem);
+ kgem_retire(&sna->kgem);
sna_deferred_free(sna);
if (sna->kgem.need_purge)