summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2011-06-24 10:23:20 +1000
committerBen Skeggs <bskeggs@redhat.com>2011-09-20 16:04:00 +1000
commita12036ba2c0a190c93e5238c5f32fdb8c023c068 (patch)
tree604f365447a806e07f31589a655b1c0a8494f669
parent987eec10dd76624d0edacdc7ecc7e1a6fc877373 (diff)
downloadlinux-3.10-a12036ba2c0a190c93e5238c5f32fdb8c023c068.tar.gz
linux-3.10-a12036ba2c0a190c93e5238c5f32fdb8c023c068.tar.bz2
linux-3.10-a12036ba2c0a190c93e5238c5f32fdb8c023c068.zip
drm/nouveau: allow a nouveau_mm to be created with holes
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mm.c47
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mm.h1
2 files changed, 28 insertions, 20 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_mm.c b/drivers/gpu/drm/nouveau/nouveau_mm.c
index 75b5dd93a32..b29ffb3d140 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mm.c
@@ -129,21 +129,25 @@ nouveau_mm_get(struct nouveau_mm *mm, int type, u32 size, u32 size_nc,
int
nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block)
{
- struct nouveau_mm_node *heap;
+ struct nouveau_mm_node *node;
+
+ if (block) {
+ mutex_init(&mm->mutex);
+ INIT_LIST_HEAD(&mm->nodes);
+ INIT_LIST_HEAD(&mm->free);
+ mm->block_size = block;
+ mm->heap_nodes = 0;
+ }
- heap = kzalloc(sizeof(*heap), GFP_KERNEL);
- if (!heap)
+ node = kzalloc(sizeof(*node), GFP_KERNEL);
+ if (!node)
return -ENOMEM;
- heap->offset = roundup(offset, block);
- heap->length = rounddown(offset + length, block) - heap->offset;
-
- mutex_init(&mm->mutex);
- mm->block_size = block;
- INIT_LIST_HEAD(&mm->nodes);
- INIT_LIST_HEAD(&mm->free);
+ node->offset = roundup(offset, mm->block_size);
+ node->length = rounddown(offset + length, mm->block_size) - node->offset;
- list_add(&heap->nl_entry, &mm->nodes);
- list_add(&heap->fl_entry, &mm->free);
+ list_add_tail(&node->nl_entry, &mm->nodes);
+ list_add_tail(&node->fl_entry, &mm->free);
+ mm->heap_nodes++;
return 0;
}
@@ -152,15 +156,18 @@ nouveau_mm_fini(struct nouveau_mm *mm)
{
struct nouveau_mm_node *node, *heap =
list_first_entry(&mm->nodes, struct nouveau_mm_node, nl_entry);
-
- if (!list_is_singular(&mm->nodes)) {
- printk(KERN_ERR "nouveau_mm not empty at destroy time!\n");
- list_for_each_entry(node, &mm->nodes, nl_entry) {
- printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n",
- node->type, node->offset, node->length);
+ int nodes = 0;
+
+ list_for_each_entry(node, &mm->nodes, nl_entry) {
+ if (nodes++ == mm->heap_nodes) {
+ printk(KERN_ERR "nouveau_mm in use at destroy time!\n");
+ list_for_each_entry(node, &mm->nodes, nl_entry) {
+ printk(KERN_ERR "0x%02x: 0x%08x 0x%08x\n",
+ node->type, node->offset, node->length);
+ }
+ WARN_ON(1);
+ return -EBUSY;
}
- WARN_ON(1);
- return -EBUSY;
}
kfree(heap);
diff --git a/drivers/gpu/drm/nouveau/nouveau_mm.h b/drivers/gpu/drm/nouveau/nouveau_mm.h
index b8fe9088b9e..57a600c35c9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_mm.h
@@ -42,6 +42,7 @@ struct nouveau_mm {
struct mutex mutex;
u32 block_size;
+ int heap_nodes;
};
int nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block);