From patchwork Sun Dec 16 17:51:41 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 1885411 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork2.kernel.org (Postfix) with ESMTP id 47073DFAC4 for ; Sun, 16 Dec 2012 17:54:51 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 2DDEAE63D9 for ; Sun, 16 Dec 2012 09:54:51 -0800 (PST) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from fireflyinternet.com (server109-228-6-235.live-servers.net [109.228.6.235]) by gabe.freedesktop.org (Postfix) with ESMTP id 5CE17E63C5 for ; Sun, 16 Dec 2012 09:54:38 -0800 (PST) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.73.22; Received: from arrandale.alporthouse.com (unverified [78.156.73.22]) by fireflyinternet.com (Firefly Internet (M1)) with ESMTP id 126229233-1500050 for multiple; Sun, 16 Dec 2012 17:54:29 +0000 From: Chris Wilson To: dri-devel@lists.freedesktop.org Subject: [PATCH] drm: Only evict the blocks required to create the requested hole Date: Sun, 16 Dec 2012 17:51:41 +0000 Message-Id: <1355680301-25749-1-git-send-email-chris@chris-wilson.co.uk> X-Mailer: git-send-email 1.7.10.4 X-Originating-IP: 78.156.73.22 Cc: Daniel Vetter X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 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 Avoid clobbering adjacent blocks if they happen to expire earlier and amalgamate together to form the requested hole. In passing this fixes a regression from commit ea7b1dd44867e9cd6bac67e7c9fc3f128b5b255c Author: Daniel Vetter Date: Fri Feb 18 17:59:12 2011 +0100 drm: mm: track free areas implicitly which swaps the end address for size (with a potential overflow) and effectively causes the eviction code to clobber almost all earlier buffers above the evictee. Signed-off-by: Chris Wilson Cc: Daniel Vetter --- drivers/gpu/drm/drm_mm.c | 58 +++++++++++++++++++++++++--------------------- include/drm/drm_mm.h | 2 +- 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 7103aa3..c93729c 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -421,6 +421,25 @@ static int check_free_hole(unsigned long start, unsigned long end, return end >= start + size; } +static int adjust_free_hole(unsigned long *start, unsigned long *end, + unsigned long size, unsigned alignment) +{ + if (*end - *start < size) + return 0; + + if (alignment) { + unsigned tmp = *start % alignment; + if (tmp) + *start += alignment - tmp; + } + + if (*end - *start < size) + return 0; + + *end = *start + size; + return 1; +} + struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm, unsigned long size, unsigned alignment, @@ -545,7 +564,7 @@ void drm_mm_init_scan(struct drm_mm *mm, mm->scan_size = size; mm->scanned_blocks = 0; mm->scan_hit_start = 0; - mm->scan_hit_size = 0; + mm->scan_hit_end = 0; mm->scan_check_range = 0; mm->prev_scanned_node = NULL; } @@ -572,7 +591,7 @@ void drm_mm_init_scan_with_range(struct drm_mm *mm, mm->scan_size = size; mm->scanned_blocks = 0; mm->scan_hit_start = 0; - mm->scan_hit_size = 0; + mm->scan_hit_end = 0; mm->scan_start = start; mm->scan_end = end; mm->scan_check_range = 1; @@ -591,8 +610,6 @@ int drm_mm_scan_add_block(struct drm_mm_node *node) struct drm_mm *mm = node->mm; struct drm_mm_node *prev_node; unsigned long hole_start, hole_end; - unsigned long adj_start; - unsigned long adj_end; mm->scanned_blocks++; @@ -612,24 +629,21 @@ int drm_mm_scan_add_block(struct drm_mm_node *node) hole_start = drm_mm_hole_node_start(prev_node); hole_end = drm_mm_hole_node_end(prev_node); - adj_start = hole_start; - adj_end = hole_end; - if (mm->color_adjust) - mm->color_adjust(prev_node, mm->scan_color, &adj_start, &adj_end); + mm->color_adjust(prev_node, mm->scan_color, + &hole_start, &hole_end); if (mm->scan_check_range) { - if (adj_start < mm->scan_start) - adj_start = mm->scan_start; - if (adj_end > mm->scan_end) - adj_end = mm->scan_end; + if (hole_start < mm->scan_start) + hole_start = mm->scan_start; + if (hole_end > mm->scan_end) + hole_end = mm->scan_end; } - if (check_free_hole(adj_start, adj_end, - mm->scan_size, mm->scan_alignment)) { + if (adjust_free_hole(&hole_start, &hole_end, + mm->scan_size, mm->scan_alignment)) { mm->scan_hit_start = hole_start; - mm->scan_hit_size = hole_end; - + mm->scan_hit_end = hole_end; return 1; } @@ -668,16 +682,8 @@ int drm_mm_scan_remove_block(struct drm_mm_node *node) INIT_LIST_HEAD(&node->node_list); list_add(&node->node_list, &prev_node->node_list); - /* Only need to check for containement because start&size for the - * complete resulting free block (not just the desired part) is - * stored. */ - if (node->start >= mm->scan_hit_start && - node->start + node->size - <= mm->scan_hit_start + mm->scan_hit_size) { - return 1; - } - - return 0; + return (node->start + node->size >= mm->scan_hit_start && + node->start <= mm->scan_hit_end); } EXPORT_SYMBOL(drm_mm_scan_remove_block); diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index 9a08a45..9e06ca1 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h @@ -70,7 +70,7 @@ struct drm_mm { unsigned long scan_color; unsigned long scan_size; unsigned long scan_hit_start; - unsigned scan_hit_size; + unsigned long scan_hit_end; unsigned scanned_blocks; unsigned long scan_start; unsigned long scan_end;