From patchwork Fri Nov 12 17:36:36 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Vetter X-Patchwork-Id: 320212 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id oACHbksN019328 for ; Fri, 12 Nov 2010 17:38:06 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 1F237A17C5 for ; Fri, 12 Nov 2010 09:37:46 -0800 (PST) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail.ffwll.ch (cable-static-49-187.intergga.ch [157.161.49.187]) by gabe.freedesktop.org (Postfix) with ESMTP id 50301A17E9 for ; Fri, 12 Nov 2010 09:34:04 -0800 (PST) Received: by mail.ffwll.ch (Postfix, from userid 1000) id 0860920C20C; Fri, 12 Nov 2010 18:37:12 +0100 (CET) X-Spam-ASN: X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on orange.ffwll.ch X-Spam-Level: X-Spam-Hammy: 0.000-+--HTo:U*dri-devel, 0.000-+--H*UA:git-send-email, 0.000-+--H*x:git-send-email X-Spam-Status: No, score=-4.4 required=6.0 tests=ALL_TRUSTED,BAYES_00 autolearn=ham version=3.2.5 X-Spam-Spammy: 0.963-+--H*r:mail.ffwll.ch, 0.958-+--H*m:ffwll, 0.944-+--H*Ad:U*daniel.vetter Received: from viiv.ffwll.ch (viiv.ffwll.ch [192.168.23.128]) by mail.ffwll.ch (Postfix) with ESMTP id BE37620C219; Fri, 12 Nov 2010 18:36:56 +0100 (CET) Received: from daniel by viiv.ffwll.ch with local (Exim 4.72) (envelope-from ) id 1PGxYW-0004Ld-Ei; Fri, 12 Nov 2010 18:36:56 +0100 From: Daniel Vetter To: dri-devel@lists.freedesktop.org Subject: [PATCH 4/9] drm: mm: add api for embedding struct drm_mm_node Date: Fri, 12 Nov 2010 18:36:36 +0100 Message-Id: <1289583401-16605-5-git-send-email-daniel.vetter@ffwll.ch> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1289583401-16605-1-git-send-email-daniel.vetter@ffwll.ch> References: <1289583401-16605-1-git-send-email-daniel.vetter@ffwll.ch> Cc: Daniel Vetter X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.11 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Fri, 12 Nov 2010 17:38:06 +0000 (UTC) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index fecb406..d6432f9 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -124,6 +124,8 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node, unsigned long hole_start = drm_mm_hole_node_start(hole_node); unsigned long hole_end = drm_mm_hole_node_end(hole_node); + BUG_ON(!hole_node->hole_follows || node->allocated); + if (alignment) tmp = hole_start % alignment; @@ -136,6 +138,7 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node, node->start = hole_start + wasted; node->size = size; node->mm = mm; + node->allocated = 1; INIT_LIST_HEAD(&node->hole_stack); list_add(&node->node_list, &hole_node->node_list); @@ -157,8 +160,6 @@ struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node, { struct drm_mm_node *node; - BUG_ON(!hole_node->hole_follows); - node = drm_mm_kmalloc(hole_node->mm, atomic); if (unlikely(node == NULL)) return NULL; @@ -169,6 +170,26 @@ struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node, } EXPORT_SYMBOL(drm_mm_get_block_generic); +/** + * Search for free space and insert a preallocated memory node. Returns + * -ENOSPC if no suitable free area is available. The preallocated memory node + * must be cleared. + */ +int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node, + unsigned long size, unsigned alignment) +{ + struct drm_mm_node *hole_node; + + hole_node = drm_mm_search_free(mm, size, alignment, 0); + if (!hole_node) + return -ENOSPC; + + drm_mm_insert_helper(hole_node, node, size, alignment); + + return 0; +} +EXPORT_SYMBOL(drm_mm_insert_node); + static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, struct drm_mm_node *node, unsigned long size, unsigned alignment, @@ -179,6 +200,8 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, unsigned long hole_start = drm_mm_hole_node_start(hole_node); unsigned long hole_end = drm_mm_hole_node_end(hole_node); + BUG_ON(!hole_node->hole_follows || node->allocated); + if (hole_start < start) wasted += start - hole_start; if (alignment) @@ -195,6 +218,7 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, node->start = hole_start + wasted; node->size = size; node->mm = mm; + node->allocated = 1; INIT_LIST_HEAD(&node->hole_stack); list_add(&node->node_list, &hole_node->node_list); @@ -219,8 +243,6 @@ struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *hole_node { struct drm_mm_node *node; - BUG_ON(!hole_node->hole_follows); - node = drm_mm_kmalloc(hole_node->mm, atomic); if (unlikely(node == NULL)) return NULL; @@ -232,14 +254,34 @@ struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *hole_node } EXPORT_SYMBOL(drm_mm_get_block_range_generic); -/* - * Put a block. Merge with the previous and / or next block if they are free. - * Otherwise add to the free stack. +/** + * Search for free space and insert a preallocated memory node. Returns + * -ENOSPC if no suitable free area is available. This is for range + * restricted allocations. The preallocated memory node must be cleared. */ - -void drm_mm_put_block(struct drm_mm_node *node) +int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node, + unsigned long size, unsigned alignment, + unsigned long start, unsigned long end) { + struct drm_mm_node *hole_node; + + hole_node = drm_mm_search_free_in_range(mm, size, alignment, + start, end, 0); + if (!hole_node) + return -ENOSPC; + + drm_mm_insert_helper_range(hole_node, node, size, alignment, + start, end); + return 0; +} +EXPORT_SYMBOL(drm_mm_insert_node_in_range); + +/** + * Remove a memory node from the allocator. + */ +void drm_mm_remove_node(struct drm_mm_node *node) +{ struct drm_mm *mm = node->mm; struct drm_mm_node *prev_node; @@ -264,6 +306,22 @@ void drm_mm_put_block(struct drm_mm_node *node) list_move(&prev_node->hole_stack, &mm->hole_stack); list_del(&node->node_list); + node->allocated = 0; +} +EXPORT_SYMBOL(drm_mm_remove_node); + +/* + * Remove a memory node from the allocator and free the allocated struct + * drm_mm_node. Only to be used on a struct drm_mm_node obtained by one of the + * drm_mm_get_block functions. + */ +void drm_mm_put_block(struct drm_mm_node *node) +{ + + struct drm_mm *mm = node->mm; + + drm_mm_remove_node(node); + spin_lock(&mm->unused_lock); if (mm->num_unused < MM_UNUSED_TARGET) { list_add(&node->node_list, &mm->unused_nodes); @@ -368,6 +426,23 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, EXPORT_SYMBOL(drm_mm_search_free_in_range); /** + * Moves an allocation. To be used with embedded struct drm_mm_node. + */ +void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new) +{ + list_replace(&old->node_list, &new->node_list); + list_replace(&old->node_list, &new->hole_stack); + new->hole_follows = old->hole_follows; + new->mm = old->mm; + new->start = old->start; + new->size = old->size; + + old->allocated = 0; + new->allocated = 1; +} +EXPORT_SYMBOL(drm_mm_replace_node); + +/** * Initializa lru scanning. * * This simply sets up the scanning routines with the parameters for the desired diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index 34fa36f..17a070e 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -49,6 +49,7 @@ struct drm_mm_node { unsigned scanned_prev_free : 1; unsigned scanned_next_free : 1; unsigned scanned_preceeds_hole : 1; + unsigned allocated : 1; unsigned long start; unsigned long size; struct drm_mm *mm; @@ -73,6 +74,11 @@ struct drm_mm { unsigned long scan_end; }; +static inline bool drm_mm_node_allocated(struct drm_mm_node *node) +{ + return node->allocated; +} + static inline bool drm_mm_initialized(struct drm_mm *mm) { return mm->hole_stack.next; @@ -126,7 +132,15 @@ static inline struct drm_mm_node *drm_mm_get_block_atomic_range( return drm_mm_get_block_range_generic(parent, size, alignment, start, end, 1); } +extern int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node, + unsigned long size, unsigned alignment); +extern int drm_mm_insert_node_in_range(struct drm_mm *mm, + struct drm_mm_node *node, + unsigned long size, unsigned alignment, + unsigned long start, unsigned long end); extern void drm_mm_put_block(struct drm_mm_node *cur); +extern void drm_mm_remove_node(struct drm_mm_node *node); +extern void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new); extern struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, unsigned long size, unsigned alignment, @@ -142,11 +156,6 @@ extern int drm_mm_init(struct drm_mm *mm, unsigned long start, unsigned long size); extern void drm_mm_takedown(struct drm_mm *mm); extern int drm_mm_clean(struct drm_mm *mm); -extern unsigned long drm_mm_tail_space(struct drm_mm *mm); -extern int drm_mm_remove_space_from_tail(struct drm_mm *mm, - unsigned long size); -extern int drm_mm_add_space_to_tail(struct drm_mm *mm, - unsigned long size, int atomic); extern int drm_mm_pre_get(struct drm_mm *mm); static inline struct drm_mm *drm_get_mm(struct drm_mm_node *block)