[PATCH 5/6] drm/radeon: validate relocations in the order determined by userspace (original) (raw)

Christian König deathsimple at vodafone.de
Thu Feb 27 01:29:24 PST 2014


Am 26.02.2014 19:25, schrieb Marek Olšák:

From: Marek Olšák <marek.olsak at amd.com>

Userspace should set the first 4 bits of drmradeoncsreloc::flags to a number from 0 to 15. The higher the number, the higher the priority, which means a buffer with a higher number will be validated sooner. The old behavior is preserved: Buffers used for write are prioritized over read-only buffers if the userspace doesn't set the number. v2: add buffers to buckets directly, then concatenate them Signed-off-by: Marek Olšák <marek.olsak at amd.com> --- drivers/gpu/drm/radeon/radeon.h | 2 +- drivers/gpu/drm/radeon/radeoncs.c | 68 ++++++++++++++++++++++++++++++++-- drivers/gpu/drm/radeon/radeonobject.c | 10 ----- drivers/gpu/drm/radeon/radeonobject.h | 2 - 4 files changed, 66 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index d37a57a..f7a3174 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -481,7 +481,7 @@ struct radeonbolist { struct ttmvalidatebuffer tv; struct radeonbo *bo; uint64t gpuoffset; - bool written; + unsigned priority;

As far as I can see priority is only used temporary in radeon_cs_parser_relocs, so we probably don't need it in here.

Apart from that patch looks good to me, Christian.

unsigned domain; unsigned altdomain; u32 tilingflags; diff --git a/drivers/gpu/drm/radeon/radeoncs.c b/drivers/gpu/drm/radeon/radeoncs.c index d49a3f7..779fa02 100644 --- a/drivers/gpu/drm/radeon/radeoncs.c +++ b/drivers/gpu/drm/radeon/radeoncs.c @@ -31,10 +31,57 @@ #include "radeon.h" #include "radeontrace.h"

+#define RADEONCSMAXPRIORITY 33u +#define RADEONCSMAXBUCKET (RADEONCSMAXPRIORITY / 2u) +#define RADEONCSNUMBUCKETS (RADEONCSMAXBUCKET + 1u) + +/* This is based on the bucket sort with O(n) time complexity. + * Relocations are sorted from the highest to the lowest priority as + * they are added. + * + * Odd numbers are added at the head of a bucket and even numbers are + * added at the tail, therefore all buckets are always sorted. */ +struct radeoncsbuckets { + struct listhead bucket[RADEONCSNUMBUCKETS]; +}; + +static void radeoncsbucketsinit(struct radeoncsbuckets *b) +{ + unsigned i; + + for (i = 0; i < RADEONCSNUMBUCKETS; i++)_ _+ INITLISTHEAD(&b->bucket[i]); +} + +static void radeoncsbucketsadd(struct radeoncsbuckets *b, + struct radeonbolist *reloc) +{ + unsigned priority = reloc->priority; + unsigned i = min(priority / 2u, RADEONCSMAXBUCKET); + + if (priority % 2 == 1) { + listadd(&reloc->tv.head, &b->bucket[i]); + } else { + listaddtail(&reloc->tv.head, &b->bucket[i]); + } +} + +static void radeoncsbucketsgetlist(struct radeoncsbuckets *b, + struct listhead *outlist) +{ + unsigned i; + + /* Connect the sorted buckets in the output list. */ + for (i = 0; i < RADEONCSNUMBUCKETS; i++) {_ _+ listsplice(&b->bucket[i], outlist); + } +} + static int radeoncsparserrelocs(struct radeoncsparser *p) { struct drmdevice *ddev = p->rdev->ddev; struct radeoncschunk *chunk; + struct radeoncsbuckets buckets; unsigned i, j; bool duplicate; @@ -53,6 +100,9 @@ static int radeoncsparserrelocs(struct radeoncsparser *p) if (p->relocs == NULL) { return -ENOMEM; } + + radeoncsbucketsinit(&buckets); + for (i = 0; i < p->nrelocs; i++) { struct drmradeoncsreloc *r; @@ -80,7 +130,15 @@ static int radeoncsparserrelocs(struct radeoncsparser *p) p->relocsptr[i] = &p->relocs[i]; p->relocs[i].robj = gemtoradeonbo(p->relocs[i].gobj); p->relocs[i].lobj.bo = p->relocs[i].robj; - p->relocs[i].lobj.written = !!r->writedomain; + + /* The userspace buffer priorities are from 0 to 15. A higher + * number means the buffer is more important. + * Also, the buffers used for write have a higher priority than + * the buffers used for read only, which doubles the range + * to 0 to 31. Numbers 32 and 33 are reserved for the kernel + * driver. + */ + p->relocs[i].lobj.priority = (r->flags & 0xf) * 2 + !!r->writedomain; /* the first reloc of an UVD job is the msg and that must be in VRAM, also but everything into VRAM on AGP cards to avoid @@ -94,6 +152,8 @@ static int radeoncsparserrelocs(struct radeoncsparser *p) p->relocs[i].lobj.altdomain = RADEONGEMDOMAINVRAM; + /* prioritize this over any other relocation */ + p->relocs[i].lobj.priority = 32; } else { uint32t domain = r->writedomain ? r->writedomain : r->readdomains; @@ -107,9 +167,11 @@ static int radeoncsparserrelocs(struct radeoncsparser *p) p->relocs[i].lobj.tv.bo = &p->relocs[i].robj->tbo; p->relocs[i].handle = r->handle; - radeonbolistaddobject(&p->relocs[i].lobj, - &p->validated); + radeoncsbucketsadd(&buckets, &p->relocs[i].lobj); } + + radeoncsbucketsgetlist(&buckets, &p->validated); + return radeonbolistvalidate(&p->ticket, &p->validated, p->ring); } diff --git a/drivers/gpu/drm/radeon/radeonobject.c b/drivers/gpu/drm/radeon/radeonobject.c index d676ee2..19042ae 100644 --- a/drivers/gpu/drm/radeon/radeonobject.c +++ b/drivers/gpu/drm/radeon/radeonobject.c @@ -368,16 +368,6 @@ void radeonbofini(struct radeondevice *rdev) archphyswcdel(rdev->mc.vrammtrr); } -void radeonbolistaddobject(struct radeonbolist *lobj, - struct listhead *head) -{ - if (lobj->written) { - listadd(&lobj->tv.head, head); - } else { - listaddtail(&lobj->tv.head, head); - } -} - int radeonbolistvalidate(struct wwacquirectx *ticket, struct listhead *head, int ring) { diff --git a/drivers/gpu/drm/radeon/radeonobject.h b/drivers/gpu/drm/radeon/radeonobject.h index a9a8c11..6c3ca9e 100644 --- a/drivers/gpu/drm/radeon/radeonobject.h +++ b/drivers/gpu/drm/radeon/radeonobject.h @@ -138,8 +138,6 @@ extern int radeonboevictvram(struct radeondevice *rdev); extern void radeonboforcedelete(struct radeondevice *rdev); extern int radeonboinit(struct radeondevice *rdev); extern void radeonbofini(struct radeondevice *rdev); -extern void radeonbolistaddobject(struct radeonbolist *lobj, - struct listhead *head); extern int radeonbolistvalidate(struct wwacquirectx *ticket, struct listhead *head, int ring); extern int radeonbofbdevmmap(struct radeonbo *bo,



More information about the dri-devel mailing list