[PATCH] radeon: preallocate memory for command stream parsing

From: Jerome Glisse
Date: Tue Jun 23 2009 - 15:46:23 EST


Command stream parsing is the most common operation and can
happen hundred of times per second, we don't want to allocate/free
memory each time this ioctl is call. This rework the ioctl
to avoid doing so by allocating temporary memory along the
ib pool.

Signed-off-by: Jerome Glisse <jglisse@xxxxxxxxxx>
---
drivers/gpu/drm/radeon/r100.c | 27 +++---
drivers/gpu/drm/radeon/r300.c | 6 +-
drivers/gpu/drm/radeon/radeon.h | 110 ++++++++++----------
drivers/gpu/drm/radeon/radeon_cs.c | 186 +++++++++++++++-------------------
drivers/gpu/drm/radeon/radeon_ring.c | 23 ++++
5 files changed, 177 insertions(+), 175 deletions(-)

diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index c550932..56ef9f7 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -699,7 +699,7 @@ void r100_cs_dump_packet(struct radeon_cs_parser *p,
unsigned idx;

ib = p->ib->ptr;
- ib_chunk = &p->chunks[p->chunk_ib_idx];
+ ib_chunk = &p->ibc;
idx = pkt->idx;
for (i = 0; i <= (pkt->count + 1); i++, idx++) {
DRM_INFO("ib[%d]=0x%08X\n", idx, ib[idx]);
@@ -718,14 +718,15 @@ int r100_cs_packet_parse(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt,
unsigned idx)
{
- struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
- uint32_t header = ib_chunk->kdata[idx];
+ struct radeon_cs_chunk *ib_chunk = &p->ibc;
+ uint32_t header;

if (idx >= ib_chunk->length_dw) {
DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
idx, ib_chunk->length_dw);
return -EINVAL;
}
+ header = ib_chunk->kdata[idx];
pkt->idx = idx;
pkt->type = CP_PACKET_GET_TYPE(header);
pkt->count = CP_PACKET_GET_COUNT(header);
@@ -767,18 +768,16 @@ int r100_cs_packet_next_reloc(struct radeon_cs_parser *p,
struct radeon_cs_reloc **cs_reloc)
{
struct radeon_cs_chunk *ib_chunk;
- struct radeon_cs_chunk *relocs_chunk;
struct radeon_cs_packet p3reloc;
unsigned idx;
int r;

- if (p->chunk_relocs_idx == -1) {
+ if (p->relocs == NULL) {
DRM_ERROR("No relocation chunk !\n");
return -EINVAL;
}
*cs_reloc = NULL;
- ib_chunk = &p->chunks[p->chunk_ib_idx];
- relocs_chunk = &p->chunks[p->chunk_relocs_idx];
+ ib_chunk = &p->ibc;
r = r100_cs_packet_parse(p, &p3reloc, p->idx);
if (r) {
return r;
@@ -791,14 +790,14 @@ int r100_cs_packet_next_reloc(struct radeon_cs_parser *p,
return -EINVAL;
}
idx = ib_chunk->kdata[p3reloc.idx + 1];
- if (idx >= relocs_chunk->length_dw) {
+ if ((idx / 4) >= p->nrelocs) {
DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
- idx, relocs_chunk->length_dw);
+ idx, p->nrelocs * 4);
r100_cs_dump_packet(p, &p3reloc);
return -EINVAL;
}
/* FIXME: we assume reloc size is 4 dwords */
- *cs_reloc = p->relocs_ptr[(idx / 4)];
+ *cs_reloc = p->relocs_ptr[idx / 4];
return 0;
}

@@ -816,7 +815,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
int r;

ib = p->ib->ptr;
- ib_chunk = &p->chunks[p->chunk_ib_idx];
+ ib_chunk = &p->ibc;
idx = pkt->idx + 1;
reg = pkt->reg;
onereg = false;
@@ -897,7 +896,7 @@ int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p,
struct radeon_cs_chunk *ib_chunk;
unsigned idx;

- ib_chunk = &p->chunks[p->chunk_ib_idx];
+ ib_chunk = &p->ibc;
idx = pkt->idx + 1;
if ((ib_chunk->kdata[idx+2] + 1) > radeon_object_size(robj)) {
DRM_ERROR("[drm] Buffer too small for PACKET3 INDX_BUFFER "
@@ -920,7 +919,7 @@ static int r100_packet3_check(struct radeon_cs_parser *p,
int r;

ib = p->ib->ptr;
- ib_chunk = &p->chunks[p->chunk_ib_idx];
+ ib_chunk = &p->ibc;
idx = pkt->idx + 1;
switch (pkt->opcode) {
case PACKET3_3D_LOAD_VBPNTR:
@@ -1027,7 +1026,7 @@ int r100_cs_parse(struct radeon_cs_parser *p)
if (r) {
return r;
}
- } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
+ } while (p->idx < p->ibc.length_dw);
return 0;
}

diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index e2ed5bc..2b2199e 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -1024,7 +1024,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
int r;

ib = p->ib->ptr;
- ib_chunk = &p->chunks[p->chunk_ib_idx];
+ ib_chunk = &p->ibc;
track = (struct r300_cs_track*)p->track;
switch(reg) {
case RADEON_DST_PITCH_OFFSET:
@@ -1361,7 +1361,7 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
int r;

ib = p->ib->ptr;
- ib_chunk = &p->chunks[p->chunk_ib_idx];
+ ib_chunk = &p->ibc;
idx = pkt->idx + 1;
track = (struct r300_cs_track*)p->track;
switch(pkt->opcode) {
@@ -1520,7 +1520,7 @@ int r300_cs_parse(struct radeon_cs_parser *p)
if (r) {
return r;
}
- } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
+ } while (p->idx < p->ibc.length_dw);
return 0;
}

diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index d61f2fc..1bea78a 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -352,6 +352,56 @@ void radeon_irq_kms_fini(struct radeon_device *rdev);


/*
+ * CS.
+ */
+struct radeon_ib;
+
+struct radeon_cs_reloc {
+ struct drm_gem_object *gobj;
+ struct radeon_object *robj;
+ struct radeon_object_list lobj;
+ uint32_t handle;
+ uint32_t flags;
+};
+
+struct radeon_cs_chunk {
+ uint32_t chunk_id;
+ uint32_t length_dw;
+ uint32_t *kdata;
+};
+
+struct radeon_cs_parser {
+ struct radeon_device *rdev;
+ struct drm_file *filp;
+ struct radeon_cs_chunk ibc;
+ /* IB */
+ unsigned idx;
+ /* relocations */
+ unsigned nrelocs;
+ struct radeon_cs_reloc *relocs;
+ struct radeon_cs_reloc **relocs_ptr;
+ struct list_head validated;
+ struct radeon_ib *ib;
+ void *track;
+};
+
+struct radeon_cs_packet {
+ unsigned idx;
+ unsigned type;
+ unsigned reg;
+ unsigned opcode;
+ int count;
+ unsigned one_reg_wr;
+};
+
+typedef int (*radeon_packet0_check_t)(struct radeon_cs_parser *p,
+ struct radeon_cs_packet *pkt,
+ unsigned idx, unsigned reg);
+typedef int (*radeon_packet3_check_t)(struct radeon_cs_parser *p,
+ struct radeon_cs_packet *pkt);
+
+
+/*
* CP & ring.
*/
struct radeon_ib {
@@ -360,12 +410,18 @@ struct radeon_ib {
uint64_t gpu_addr;
struct radeon_fence *fence;
volatile uint32_t *ptr;
+ uint32_t *ib;
+ struct radeon_cs_reloc *relocs;
+ struct radeon_cs_reloc **relocs_ptr;
uint32_t length_dw;
};

struct radeon_ib_pool {
struct mutex mutex;
struct radeon_object *robj;
+ uint32_t *ib;
+ struct radeon_cs_reloc *relocs;
+ struct radeon_cs_reloc **relocs_ptr;
struct list_head scheduled_ibs;
struct radeon_ib ibs[RADEON_IB_POOL_SIZE];
bool ready;
@@ -405,60 +461,6 @@ void radeon_ring_fini(struct radeon_device *rdev);


/*
- * CS.
- */
-struct radeon_cs_reloc {
- struct drm_gem_object *gobj;
- struct radeon_object *robj;
- struct radeon_object_list lobj;
- uint32_t handle;
- uint32_t flags;
-};
-
-struct radeon_cs_chunk {
- uint32_t chunk_id;
- uint32_t length_dw;
- uint32_t *kdata;
-};
-
-struct radeon_cs_parser {
- struct radeon_device *rdev;
- struct drm_file *filp;
- /* chunks */
- unsigned nchunks;
- struct radeon_cs_chunk *chunks;
- uint64_t *chunks_array;
- /* IB */
- unsigned idx;
- /* relocations */
- unsigned nrelocs;
- struct radeon_cs_reloc *relocs;
- struct radeon_cs_reloc **relocs_ptr;
- struct list_head validated;
- /* indices of various chunks */
- int chunk_ib_idx;
- int chunk_relocs_idx;
- struct radeon_ib *ib;
- void *track;
-};
-
-struct radeon_cs_packet {
- unsigned idx;
- unsigned type;
- unsigned reg;
- unsigned opcode;
- int count;
- unsigned one_reg_wr;
-};
-
-typedef int (*radeon_packet0_check_t)(struct radeon_cs_parser *p,
- struct radeon_cs_packet *pkt,
- unsigned idx, unsigned reg);
-typedef int (*radeon_packet3_check_t)(struct radeon_cs_parser *p,
- struct radeon_cs_packet *pkt);
-
-
-/*
* AGP
*/
int radeon_agp_init(struct radeon_device *rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
index b843f9b..8fb08fa 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -29,61 +29,52 @@
#include "radeon_reg.h"
#include "radeon.h"

-void r100_cs_dump_packet(struct radeon_cs_parser *p,
- struct radeon_cs_packet *pkt);
-
-int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
+static int radeon_cs_parser_reloc(struct radeon_cs_parser *p,
+ struct drm_radeon_cs_chunk *chunk)
{
- struct drm_device *ddev = p->rdev->ddev;
- struct radeon_cs_chunk *chunk;
- unsigned i, j;
+ struct drm_radeon_cs_reloc __user *reloc_ptr;
+ struct drm_radeon_cs_reloc reloc;
+ unsigned i, j, c;
bool duplicate;

- if (p->chunk_relocs_idx == -1) {
- return 0;
- }
- chunk = &p->chunks[p->chunk_relocs_idx];
- /* FIXME: we assume that each relocs use 4 dwords */
p->nrelocs = chunk->length_dw / 4;
- p->relocs_ptr = kcalloc(p->nrelocs, sizeof(void *), GFP_KERNEL);
- if (p->relocs_ptr == NULL) {
- return -ENOMEM;
- }
- p->relocs = kcalloc(p->nrelocs, sizeof(struct radeon_cs_reloc), GFP_KERNEL);
- if (p->relocs == NULL) {
- return -ENOMEM;
+ if (p->nrelocs > 1024) {
+ DRM_ERROR("Too many relocations %d\n", p->nrelocs);
+ return -EINVAL;
}
- for (i = 0; i < p->nrelocs; i++) {
- struct drm_radeon_cs_reloc *r;
-
+ for (i = 0, c = 0; i < p->nrelocs; i++) {
+ reloc_ptr = (void __user*)(unsigned long)(chunk->chunk_data + i * 16);
+ if (DRM_COPY_FROM_USER(&reloc, reloc_ptr, 16)) {
+ return -EFAULT;
+ }
duplicate = false;
- r = (struct drm_radeon_cs_reloc *)&chunk->kdata[i*4];
- for (j = 0; j < p->nrelocs; j++) {
- if (r->handle == p->relocs[j].handle) {
+ for (j = 0; j < c; j++) {
+ if (reloc.handle == p->relocs[j].handle) {
p->relocs_ptr[i] = &p->relocs[j];
duplicate = true;
break;
}
}
if (!duplicate) {
- p->relocs[i].gobj = drm_gem_object_lookup(ddev,
+ p->relocs[i].gobj = drm_gem_object_lookup(p->rdev->ddev,
p->filp,
- r->handle);
+ reloc.handle);
if (p->relocs[i].gobj == NULL) {
DRM_ERROR("gem object lookup failed 0x%x\n",
- r->handle);
+ reloc.handle);
return -EINVAL;
}
p->relocs_ptr[i] = &p->relocs[i];
p->relocs[i].robj = p->relocs[i].gobj->driver_private;
p->relocs[i].lobj.robj = p->relocs[i].robj;
- p->relocs[i].lobj.rdomain = r->read_domains;
- p->relocs[i].lobj.wdomain = r->write_domain;
- p->relocs[i].handle = r->handle;
- p->relocs[i].flags = r->flags;
+ p->relocs[i].lobj.rdomain = reloc.read_domains;
+ p->relocs[i].lobj.wdomain = reloc.write_domain;
+ p->relocs[i].handle = reloc.handle;
+ p->relocs[i].flags = reloc.flags;
INIT_LIST_HEAD(&p->relocs[i].lobj.list);
radeon_object_list_add_object(&p->relocs[i].lobj,
&p->validated);
+ c++;
}
}
return radeon_object_list_validate(&p->validated, p->ib->fence);
@@ -92,65 +83,53 @@ int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
{
struct drm_radeon_cs *cs = data;
- uint64_t *chunk_array_ptr;
- unsigned size, i;
+ unsigned i;
+ int r;
+ bool found_ib = false;

- if (!cs->num_chunks) {
- return 0;
- }
- /* get chunks */
- INIT_LIST_HEAD(&p->validated);
- p->idx = 0;
- p->chunk_ib_idx = -1;
- p->chunk_relocs_idx = -1;
- p->chunks_array = kcalloc(cs->num_chunks, sizeof(uint64_t), GFP_KERNEL);
- if (p->chunks_array == NULL) {
- return -ENOMEM;
- }
- chunk_array_ptr = (uint64_t *)(unsigned long)(cs->chunks);
- if (DRM_COPY_FROM_USER(p->chunks_array, chunk_array_ptr,
- sizeof(uint64_t)*cs->num_chunks)) {
- return -EFAULT;
- }
- p->nchunks = cs->num_chunks;
- p->chunks = kcalloc(p->nchunks, sizeof(struct radeon_cs_chunk), GFP_KERNEL);
- if (p->chunks == NULL) {
- return -ENOMEM;
- }
- for (i = 0; i < p->nchunks; i++) {
- struct drm_radeon_cs_chunk __user **chunk_ptr = NULL;
- struct drm_radeon_cs_chunk user_chunk;
+ for (i = 0; i < cs->num_chunks; i++) {
+ struct drm_radeon_cs_chunk __user *chunk_ptr = NULL;
+ struct drm_radeon_cs_chunk chunk;
uint32_t __user *cdata;
+ unsigned tmp;
+ u64 ptr;

- chunk_ptr = (void __user*)(unsigned long)p->chunks_array[i];
- if (DRM_COPY_FROM_USER(&user_chunk, chunk_ptr,
- sizeof(struct drm_radeon_cs_chunk))) {
+ chunk_ptr = (void __user*)(unsigned long)(cs->chunks + i * 8);
+ if (DRM_COPY_FROM_USER(&ptr, chunk_ptr, sizeof(u64))) {
return -EFAULT;
}
- p->chunks[i].chunk_id = user_chunk.chunk_id;
- if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_RELOCS) {
- p->chunk_relocs_idx = i;
- }
- if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_IB) {
- p->chunk_ib_idx = i;
- }
- p->chunks[i].length_dw = user_chunk.length_dw;
- cdata = (uint32_t *)(unsigned long)user_chunk.chunk_data;
-
- p->chunks[i].kdata = NULL;
- size = p->chunks[i].length_dw * sizeof(uint32_t);
- p->chunks[i].kdata = kzalloc(size, GFP_KERNEL);
- if (p->chunks[i].kdata == NULL) {
- return -ENOMEM;
- }
- if (DRM_COPY_FROM_USER(p->chunks[i].kdata, cdata, size)) {
+ chunk_ptr = (void __user*)(unsigned long)ptr;
+ if (DRM_COPY_FROM_USER(&chunk, chunk_ptr, sizeof(struct drm_radeon_cs_chunk))) {
return -EFAULT;
}
- }
- if (p->chunks[p->chunk_ib_idx].length_dw > (16 * 1024)) {
- DRM_ERROR("cs IB too big: %d\n",
- p->chunks[p->chunk_ib_idx].length_dw);
- return -EINVAL;
+ switch (chunk.chunk_id) {
+ case RADEON_CHUNK_ID_RELOCS:
+ r = radeon_cs_parser_reloc(p, &chunk);
+ if (r) {
+ return r;
+ }
+ break;
+ case RADEON_CHUNK_ID_IB:
+ if (found_ib) {
+ DRM_ERROR("Multiple IB chunks not supported\n");
+ return -EINVAL;
+ }
+ found_ib = true;
+ if (chunk.length_dw > 16 * 1024) {
+ DRM_ERROR("cs IB too big: %d\n", chunk.length_dw);
+ return -EINVAL;
+ }
+ p->ibc.chunk_id = chunk.chunk_id;
+ p->ibc.length_dw = chunk.length_dw;
+ tmp = p->ibc.length_dw * sizeof(u32);
+ cdata = (uint32_t *)(unsigned long)chunk.chunk_data;
+ if (DRM_COPY_FROM_USER(p->ibc.kdata, cdata, tmp)) {
+ return -EFAULT;
+ }
+ break;
+ default:
+ break;
+ }
}
return 0;
}
@@ -179,13 +158,6 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error)
mutex_unlock(&parser->rdev->ddev->struct_mutex);
}
}
- kfree(parser->relocs);
- kfree(parser->relocs_ptr);
- for (i = 0; i < parser->nchunks; i++) {
- kfree(parser->chunks[i].kdata);
- }
- kfree(parser->chunks);
- kfree(parser->chunks_array);
radeon_ib_free(parser->rdev, &parser->ib);
}

@@ -193,7 +165,6 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
{
struct radeon_device *rdev = dev->dev_private;
struct radeon_cs_parser parser;
- struct radeon_cs_chunk *ib_chunk;
int r;

mutex_lock(&rdev->cs_mutex);
@@ -202,36 +173,43 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
return -EINVAL;
}
/* initialize parser */
- memset(&parser, 0, sizeof(struct radeon_cs_parser));
+ INIT_LIST_HEAD(&parser.validated);
+ parser.idx = 0;
+ parser.ibc.kdata = NULL;
+ parser.ibc.length_dw = 0;
+ parser.relocs = NULL;
+ parser.relocs_ptr = NULL;
+ parser.ib = NULL;
parser.filp = filp;
parser.rdev = rdev;
- r = radeon_cs_parser_init(&parser, data);
+ r = radeon_ib_get(rdev, &parser.ib);
if (r) {
- DRM_ERROR("Failed to initialize parser !\n");
+ DRM_ERROR("Failed to get ib !\n");
radeon_cs_parser_fini(&parser, r);
mutex_unlock(&rdev->cs_mutex);
return r;
}
- r = radeon_ib_get(rdev, &parser.ib);
+ parser.ibc.kdata = parser.ib->ib;
+ parser.relocs = parser.ib->relocs;
+ parser.relocs_ptr = parser.ib->relocs_ptr;
+ r = radeon_cs_parser_init(&parser, data);
if (r) {
- DRM_ERROR("Failed to get ib !\n");
+ DRM_ERROR("Failed to initialize parser !\n");
radeon_cs_parser_fini(&parser, r);
mutex_unlock(&rdev->cs_mutex);
return r;
}
- r = radeon_cs_parser_relocs(&parser);
- if (r) {
- DRM_ERROR("Failed to parse relocation !\n");
+ if (parser.ibc.kdata == NULL) {
+ DRM_INFO("No IB chunk in cs, nothing to do\n");
radeon_cs_parser_fini(&parser, r);
mutex_unlock(&rdev->cs_mutex);
- return r;
+ return 0;
}
/* Copy the packet into the IB, the parser will read from the
* input memory (cached) and write to the IB (which can be
* uncached). */
- ib_chunk = &parser.chunks[parser.chunk_ib_idx];
- parser.ib->length_dw = ib_chunk->length_dw;
- memcpy((void *)parser.ib->ptr, ib_chunk->kdata, ib_chunk->length_dw*4);
+ parser.ib->length_dw = parser.ibc.length_dw;
+ memcpy((void *)parser.ib->ptr, parser.ibc.kdata, parser.ibc.length_dw * 4);
r = radeon_cs_parse(&parser);
if (r) {
DRM_ERROR("Invalid command stream !\n");
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index a853261..0026a11 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -177,6 +177,20 @@ int radeon_ib_pool_init(struct radeon_device *rdev)

/* Allocate 1M object buffer */
INIT_LIST_HEAD(&rdev->ib_pool.scheduled_ibs);
+ rdev->ib_pool.ib = drm_calloc_large(RADEON_IB_POOL_SIZE, 64 * 1024);
+ if (rdev->ib_pool.ib == NULL) {
+ return -ENOMEM;
+ }
+ rdev->ib_pool.relocs = drm_calloc_large(RADEON_IB_POOL_SIZE * 1024,
+ sizeof(struct radeon_cs_reloc));
+ if (rdev->ib_pool.relocs == NULL) {
+ return -ENOMEM;
+ }
+ rdev->ib_pool.relocs_ptr = drm_calloc_large(RADEON_IB_POOL_SIZE * 1024,
+ sizeof(void *));
+ if (rdev->ib_pool.relocs == NULL) {
+ return -ENOMEM;
+ }
r = radeon_object_create(rdev, NULL, RADEON_IB_POOL_SIZE*64*1024,
true, RADEON_GEM_DOMAIN_GTT,
false, &rdev->ib_pool.robj);
@@ -202,6 +216,9 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
rdev->ib_pool.ibs[i].ptr = ptr + offset;
rdev->ib_pool.ibs[i].idx = i;
rdev->ib_pool.ibs[i].length_dw = 0;
+ rdev->ib_pool.ibs[i].ib = &rdev->ib_pool.ib[i * 16 * 1024];
+ rdev->ib_pool.ibs[i].relocs = &rdev->ib_pool.relocs[i * 1024];
+ rdev->ib_pool.ibs[i].relocs_ptr = &rdev->ib_pool.relocs_ptr[i * 1024];
INIT_LIST_HEAD(&rdev->ib_pool.ibs[i].list);
}
bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE);
@@ -225,6 +242,12 @@ void radeon_ib_pool_fini(struct radeon_device *rdev)
radeon_object_unref(&rdev->ib_pool.robj);
rdev->ib_pool.robj = NULL;
}
+ if (rdev->ib_pool.ib)
+ drm_free_large(rdev->ib_pool.ib);
+ if (rdev->ib_pool.relocs)
+ drm_free_large(rdev->ib_pool.relocs);
+ if (rdev->ib_pool.relocs_ptr)
+ drm_free_large(rdev->ib_pool.relocs_ptr);
mutex_unlock(&rdev->ib_pool.mutex);
}

--
1.6.2.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/