From c828e20456301b0f5192a1f75e8bf8a6afd15551 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 25 Oct 2011 16:32:45 +0200 Subject: drm/via: track obj->drm_fd relations in the driver Exactly like the previous patch for sis. Signed-off-by: Daniel Vetter --- drivers/gpu/drm/via/via_mm.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/via/via_mm.c') diff --git a/drivers/gpu/drm/via/via_mm.c b/drivers/gpu/drm/via/via_mm.c index 6cc2dadae3e..19bb77cdeb4 100644 --- a/drivers/gpu/drm/via/via_mm.c +++ b/drivers/gpu/drm/via/via_mm.c @@ -115,12 +115,13 @@ void via_lastclose(struct drm_device *dev) } int via_mem_alloc(struct drm_device *dev, void *data, - struct drm_file *file_priv) + struct drm_file *file) { drm_via_mem_t *mem = data; int retval = 0; struct drm_memblock_item *item; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; + struct via_file_private *file_priv = file->driver_priv; unsigned long tmpSize; if (mem->type > VIA_MEM_AGP) { @@ -137,10 +138,10 @@ int via_mem_alloc(struct drm_device *dev, void *data, } tmpSize = (mem->size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT; - item = drm_sman_alloc(&dev_priv->sman, mem->type, tmpSize, 0, - (unsigned long)file_priv); - mutex_unlock(&dev->struct_mutex); + item = drm_sman_alloc(&dev_priv->sman, mem->type, tmpSize, 0, 0); + if (item) { + list_move(&item->owner_list, &file_priv->obj_list); mem->offset = ((mem->type == VIA_MEM_VIDEO) ? dev_priv->vram_offset : dev_priv->agp_offset) + (item->mm-> @@ -153,6 +154,7 @@ int via_mem_alloc(struct drm_device *dev, void *data, DRM_DEBUG("Video memory allocation failed\n"); retval = -ENOMEM; } + mutex_unlock(&dev->struct_mutex); return retval; } @@ -173,12 +175,13 @@ int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv) void via_reclaim_buffers_locked(struct drm_device *dev, - struct drm_file *file_priv) + struct drm_file *file) { - drm_via_private_t *dev_priv = dev->dev_private; + struct via_file_private *file_priv = file->driver_priv; + struct drm_memblock_item *entry, *next; mutex_lock(&dev->struct_mutex); - if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)file_priv)) { + if (list_empty(&file_priv->obj_list)) { mutex_unlock(&dev->struct_mutex); return; } @@ -186,7 +189,10 @@ void via_reclaim_buffers_locked(struct drm_device *dev, if (dev->driver->dma_quiescent) dev->driver->dma_quiescent(dev); - drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)file_priv); + list_for_each_entry_safe(entry, next, &file_priv->obj_list, + owner_list) { + drm_sman_free(entry); + } mutex_unlock(&dev->struct_mutex); return; } -- cgit v1.2.3-18-g5258 From 763240deb423c477b4d46c23e0b582099d4b8753 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 26 Oct 2011 22:28:07 +0200 Subject: drm/sman: rip out owner tracking In contrast to kms drivers, sis/via _always_ associated a buffer with a drm fd. So by the time we reach lastclose, all open drm fds are gone and with them their associated objects. So when sis/via call drm_sman_cleanup in their lastclose funcs, that will free 0 objects. The owner tracking now serves no purpose at all, hence rip it ou. We can't kill the corresponding fields in struct drm_memblock_item yet because we hijack these in the new driver private owner tracking. But now that drm_sman.c doesn't touch ->owner_list anymore, we need to kill the list_move hack and properly add the item to the file_priv list. Also leave the list_del(&obj->owner_list) in drm_sman_free for the moment, it will move to the drivers when sman disappears completely. v2: Remove the redundant INIT_LIST_HEAD as noted by Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/via/via_mm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/via/via_mm.c') diff --git a/drivers/gpu/drm/via/via_mm.c b/drivers/gpu/drm/via/via_mm.c index 19bb77cdeb4..e0110bc2760 100644 --- a/drivers/gpu/drm/via/via_mm.c +++ b/drivers/gpu/drm/via/via_mm.c @@ -141,7 +141,7 @@ int via_mem_alloc(struct drm_device *dev, void *data, item = drm_sman_alloc(&dev_priv->sman, mem->type, tmpSize, 0, 0); if (item) { - list_move(&item->owner_list, &file_priv->obj_list); + list_add(&item->owner_list, &file_priv->obj_list); mem->offset = ((mem->type == VIA_MEM_VIDEO) ? dev_priv->vram_offset : dev_priv->agp_offset) + (item->mm-> -- cgit v1.2.3-18-g5258 From 77ee8f3825054f23b17e9c8f728f061defd86cdc Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 25 Oct 2011 17:55:31 +0200 Subject: drm/via: track user->memblock mapping with idr Massive indirection through a hashtable for a simple key->pointer look-up actually just adds bloat. v2: Drop the misleading comment noted by Chris Wilson. Signed-off-by: Daniel Vetter --- drivers/gpu/drm/via/via_mm.c | 58 +++++++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 14 deletions(-) (limited to 'drivers/gpu/drm/via/via_mm.c') diff --git a/drivers/gpu/drm/via/via_mm.c b/drivers/gpu/drm/via/via_mm.c index e0110bc2760..e6f2b6371b4 100644 --- a/drivers/gpu/drm/via/via_mm.c +++ b/drivers/gpu/drm/via/via_mm.c @@ -118,7 +118,7 @@ int via_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file) { drm_via_mem_t *mem = data; - int retval = 0; + int retval = 0, user_key; struct drm_memblock_item *item; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; struct via_file_private *file_priv = file->driver_priv; @@ -139,23 +139,44 @@ int via_mem_alloc(struct drm_device *dev, void *data, tmpSize = (mem->size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT; item = drm_sman_alloc(&dev_priv->sman, mem->type, tmpSize, 0, 0); + if (!item) { + retval = -ENOMEM; + goto fail_alloc; + } - if (item) { - list_add(&item->owner_list, &file_priv->obj_list); - mem->offset = ((mem->type == VIA_MEM_VIDEO) ? - dev_priv->vram_offset : dev_priv->agp_offset) + - (item->mm-> - offset(item->mm, item->mm_info) << VIA_MM_ALIGN_SHIFT); - mem->index = item->user_hash.key; - } else { - mem->offset = 0; - mem->size = 0; - mem->index = 0; - DRM_DEBUG("Video memory allocation failed\n"); +again: + if (idr_pre_get(&dev_priv->object_idr, GFP_KERNEL) == 0) { retval = -ENOMEM; + goto fail_idr; } + + retval = idr_get_new_above(&dev_priv->object_idr, item, 1, &user_key); + if (retval == -EAGAIN) + goto again; + if (retval) + goto fail_idr; + + list_add(&item->owner_list, &file_priv->obj_list); mutex_unlock(&dev->struct_mutex); + mem->offset = ((mem->type == VIA_MEM_VIDEO) ? + dev_priv->vram_offset : dev_priv->agp_offset) + + (item->mm-> + offset(item->mm, item->mm_info) << VIA_MM_ALIGN_SHIFT); + mem->index = user_key; + + return 0; + +fail_idr: + drm_sman_free(item); +fail_alloc: + mutex_unlock(&dev->struct_mutex); + + mem->offset = 0; + mem->size = 0; + mem->index = 0; + DRM_DEBUG("Video memory allocation failed\n"); + return retval; } @@ -163,11 +184,20 @@ int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_via_private_t *dev_priv = dev->dev_private; drm_via_mem_t *mem = data; + struct drm_memblock_item *obj; int ret; mutex_lock(&dev->struct_mutex); - ret = drm_sman_free_key(&dev_priv->sman, mem->index); + obj = idr_find(&dev_priv->object_idr, mem->index); + if (obj == NULL) { + mutex_unlock(&dev->struct_mutex); + return -EINVAL; + } + + idr_remove(&dev_priv->object_idr, mem->index); + drm_sman_free(obj); mutex_unlock(&dev->struct_mutex); + DRM_DEBUG("free = 0x%lx\n", mem->index); return ret; -- cgit v1.2.3-18-g5258 From 977b4f6edd7a960dd80c1a614a7644068f866c5b Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 26 Oct 2011 22:21:13 +0200 Subject: drm/via: use drm_mm instead of drm_sman To make the transition in a piece-wise and bisectable way possible, I've hijacked the ->owner_list from drm_sman. While transitioning, the list_add was done by the driver, while the list_del was still done by the dying sman code. Now that we are in full control of ->owner_list, do the list_del ourselves. v2: Better explain the list_del trickery as suggested by Chris Wilson. Signed-off-by: Daniel Vetter --- drivers/gpu/drm/via/via_mm.c | 72 ++++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 32 deletions(-) (limited to 'drivers/gpu/drm/via/via_mm.c') diff --git a/drivers/gpu/drm/via/via_mm.c b/drivers/gpu/drm/via/via_mm.c index e6f2b6371b4..bedb23d2ece 100644 --- a/drivers/gpu/drm/via/via_mm.c +++ b/drivers/gpu/drm/via/via_mm.c @@ -28,26 +28,22 @@ #include "drmP.h" #include "via_drm.h" #include "via_drv.h" -#include "drm_sman.h" #define VIA_MM_ALIGN_SHIFT 4 #define VIA_MM_ALIGN_MASK ((1 << VIA_MM_ALIGN_SHIFT) - 1) +struct via_memblock { + struct drm_mm_node mm_node; + struct list_head owner_list; +}; + int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_via_agp_t *agp = data; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - int ret; mutex_lock(&dev->struct_mutex); - ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_AGP, 0, - agp->size >> VIA_MM_ALIGN_SHIFT); - - if (ret) { - DRM_ERROR("AGP memory manager initialisation error\n"); - mutex_unlock(&dev->struct_mutex); - return ret; - } + drm_mm_init(&dev_priv->agp_mm, 0, agp->size >> VIA_MM_ALIGN_SHIFT); dev_priv->agp_initialized = 1; dev_priv->agp_offset = agp->offset; @@ -61,17 +57,9 @@ int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_via_fb_t *fb = data; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - int ret; mutex_lock(&dev->struct_mutex); - ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_VIDEO, 0, - fb->size >> VIA_MM_ALIGN_SHIFT); - - if (ret) { - DRM_ERROR("VRAM memory manager initialisation error\n"); - mutex_unlock(&dev->struct_mutex); - return ret; - } + drm_mm_init(&dev_priv->vram_mm, 0, fb->size >> VIA_MM_ALIGN_SHIFT); dev_priv->vram_initialized = 1; dev_priv->vram_offset = fb->offset; @@ -108,9 +96,14 @@ void via_lastclose(struct drm_device *dev) return; mutex_lock(&dev->struct_mutex); - drm_sman_cleanup(&dev_priv->sman); - dev_priv->vram_initialized = 0; - dev_priv->agp_initialized = 0; + if (dev_priv->vram_initialized) { + drm_mm_takedown(&dev_priv->vram_mm); + dev_priv->vram_initialized = 0; + } + if (dev_priv->agp_initialized) { + drm_mm_takedown(&dev_priv->agp_mm); + dev_priv->agp_initialized = 0; + } mutex_unlock(&dev->struct_mutex); } @@ -119,7 +112,7 @@ int via_mem_alloc(struct drm_device *dev, void *data, { drm_via_mem_t *mem = data; int retval = 0, user_key; - struct drm_memblock_item *item; + struct via_memblock *item; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; struct via_file_private *file_priv = file->driver_priv; unsigned long tmpSize; @@ -137,13 +130,24 @@ int via_mem_alloc(struct drm_device *dev, void *data, return -EINVAL; } - tmpSize = (mem->size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT; - item = drm_sman_alloc(&dev_priv->sman, mem->type, tmpSize, 0, 0); + item = kzalloc(sizeof(*item), GFP_KERNEL); if (!item) { retval = -ENOMEM; goto fail_alloc; } + tmpSize = (mem->size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT; + if (mem->type == VIA_MEM_AGP) + retval = drm_mm_insert_node(&dev_priv->agp_mm, + &item->mm_node, + tmpSize, 0); + else + retval = drm_mm_insert_node(&dev_priv->vram_mm, + &item->mm_node, + tmpSize, 0); + if (retval) + goto fail_alloc; + again: if (idr_pre_get(&dev_priv->object_idr, GFP_KERNEL) == 0) { retval = -ENOMEM; @@ -161,15 +165,15 @@ again: mem->offset = ((mem->type == VIA_MEM_VIDEO) ? dev_priv->vram_offset : dev_priv->agp_offset) + - (item->mm-> - offset(item->mm, item->mm_info) << VIA_MM_ALIGN_SHIFT); + ((item->mm_node.start) << VIA_MM_ALIGN_SHIFT); mem->index = user_key; return 0; fail_idr: - drm_sman_free(item); + drm_mm_remove_node(&item->mm_node); fail_alloc: + kfree(item); mutex_unlock(&dev->struct_mutex); mem->offset = 0; @@ -184,7 +188,7 @@ int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_via_private_t *dev_priv = dev->dev_private; drm_via_mem_t *mem = data; - struct drm_memblock_item *obj; + struct via_memblock *obj; int ret; mutex_lock(&dev->struct_mutex); @@ -195,7 +199,9 @@ int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv) } idr_remove(&dev_priv->object_idr, mem->index); - drm_sman_free(obj); + list_del(&obj->owner_list); + drm_mm_remove_node(&obj->mm_node); + kfree(obj); mutex_unlock(&dev->struct_mutex); DRM_DEBUG("free = 0x%lx\n", mem->index); @@ -208,7 +214,7 @@ void via_reclaim_buffers_locked(struct drm_device *dev, struct drm_file *file) { struct via_file_private *file_priv = file->driver_priv; - struct drm_memblock_item *entry, *next; + struct via_memblock *entry, *next; mutex_lock(&dev->struct_mutex); if (list_empty(&file_priv->obj_list)) { @@ -221,7 +227,9 @@ void via_reclaim_buffers_locked(struct drm_device *dev, list_for_each_entry_safe(entry, next, &file_priv->obj_list, owner_list) { - drm_sman_free(entry); + list_del(&entry->owner_list); + drm_mm_remove_node(&entry->mm_node); + kfree(entry); } mutex_unlock(&dev->struct_mutex); return; -- cgit v1.2.3-18-g5258 From b5215ef1a877cd81a2558f3ddbcf784671a27588 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 8 Jan 2012 22:42:27 +0100 Subject: drm/sis|via: don't return stack garbage from free_mem ioctl Fallout from my "kill drm_sman" refactor. Unfortunately gcc seems to have failed me and not warned about this. Tested-by: Jakob Bornecrantz (on via) Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/via/via_mm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu/drm/via/via_mm.c') diff --git a/drivers/gpu/drm/via/via_mm.c b/drivers/gpu/drm/via/via_mm.c index bedb23d2ece..a3574d09a07 100644 --- a/drivers/gpu/drm/via/via_mm.c +++ b/drivers/gpu/drm/via/via_mm.c @@ -189,7 +189,6 @@ int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv) drm_via_private_t *dev_priv = dev->dev_private; drm_via_mem_t *mem = data; struct via_memblock *obj; - int ret; mutex_lock(&dev->struct_mutex); obj = idr_find(&dev_priv->object_idr, mem->index); @@ -206,7 +205,7 @@ int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv) DRM_DEBUG("free = 0x%lx\n", mem->index); - return ret; + return 0; } -- cgit v1.2.3-18-g5258