From patchwork Sun Aug 3 11:16:54 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tetsuo Handa X-Patchwork-Id: 4665891 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 72D8B9F375 for ; Sun, 3 Aug 2014 15:30:54 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6B1712017E for ; Sun, 3 Aug 2014 15:30:53 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 6D1AD20172 for ; Sun, 3 Aug 2014 15:30:52 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 254146E1B6; Sun, 3 Aug 2014 08:30:49 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from www262.sakura.ne.jp (www262.sakura.ne.jp [202.181.97.72]) by gabe.freedesktop.org (Postfix) with ESMTP id 926E76E027 for ; Sun, 3 Aug 2014 05:03:44 -0700 (PDT) Received: from fsav301.sakura.ne.jp (fsav301.sakura.ne.jp [153.120.85.132]) by www262.sakura.ne.jp (8.14.5/8.14.5) with ESMTP id s73BH1IA049822; Sun, 3 Aug 2014 20:17:01 +0900 (JST) (envelope-from penguin-kernel@I-love.SAKURA.ne.jp) Received: from 202.181.97.72 (202.181.97.72) by fsav301.sakura.ne.jp (F-Secure/virusgw_smtp/412/fsav301.sakura.ne.jp); Sun, 03 Aug 2014 20:17:01 +0900 (JST) X-Virus-Status: clean(F-Secure/virusgw_smtp/412/fsav301.sakura.ne.jp) Received: from CLAMP (KD175108057186.ppp-bb.dion.ne.jp [175.108.57.186]) (authenticated bits=0) by www262.sakura.ne.jp (8.14.5/8.14.5) with ESMTP id s73BH1cR049818; Sun, 3 Aug 2014 20:17:01 +0900 (JST) (envelope-from penguin-kernel@I-love.SAKURA.ne.jp) To: konrad.wilk@oracle.com, dchinner@redhat.com Subject: [PATCH 5/5] gpu/drm/ttm: Pass GFP flags in order to avoid deadlock. From: Tetsuo Handa References: <201406110516.HCH90692.FFFStVJMOHOLQO@I-love.SAKURA.ne.jp> <201408032014.EBE26508.FQOFtHFOSVJMOL@I-love.SAKURA.ne.jp> <201408032014.BHF60482.VFOFSMJLtHQFOO@I-love.SAKURA.ne.jp> <201408032015.EDH17687.SJOtFFLMFHVOQO@I-love.SAKURA.ne.jp> <201408032016.CFI95841.SOVHFQtFJFOLOM@I-love.SAKURA.ne.jp> In-Reply-To: <201408032016.CFI95841.SOVHFQtFJFOLOM@I-love.SAKURA.ne.jp> Message-Id: <201408032016.GHJ12425.VtFOQJFOMFSLOH@I-love.SAKURA.ne.jp> X-Mailer: Winbiff [Version 2.51 PL2] X-Accept-Language: ja,en,zh Date: Sun, 3 Aug 2014 20:16:54 +0900 Mime-Version: 1.0 X-Mailman-Approved-At: Sun, 03 Aug 2014 08:30:45 -0700 Cc: linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Spam-Status: No, score=-3.7 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RCVD_NUMERIC_HELO, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP >From cf572226bd1f67305dc5477fccdc6daa30396994 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Sun, 3 Aug 2014 20:02:31 +0900 Subject: [PATCH 5/5] gpu/drm/ttm: Pass GFP flags in order to avoid deadlock. Commit 7dc19d5a "drivers: convert shrinkers to new count/scan API" added deadlock warnings that ttm_page_pool_free() and ttm_dma_page_pool_free() are currently doing GFP_KERNEL allocation. But these functions did not get updated to receive gfp_t argument. This patch explicitly passes sc->gfp_mask or GFP_KERNEL to these functions, and removes the deadlock warning. Signed-off-by: Tetsuo Handa Cc: stable [2.6.35+] --- drivers/gpu/drm/ttm/ttm_page_alloc.c | 19 ++++++++++--------- drivers/gpu/drm/ttm/ttm_page_alloc_dma.c | 19 +++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c index edb8315..09874d6 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c @@ -297,8 +297,10 @@ static void ttm_pool_update_free_locked(struct ttm_page_pool *pool, * * @pool: to free the pages from * @free_all: If set to true will free all pages in pool + * @gfp: GFP flags. **/ -static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free) +static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free, + gfp_t gfp) { unsigned long irq_flags; struct page *p; @@ -309,8 +311,7 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free) if (NUM_PAGES_TO_ALLOC < nr_free) npages_to_free = NUM_PAGES_TO_ALLOC; - pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), - GFP_KERNEL); + pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp); if (!pages_to_free) { pr_err("Failed to allocate memory for pool free operation\n"); return 0; @@ -382,9 +383,7 @@ out: * * XXX: (dchinner) Deadlock warning! * - * ttm_page_pool_free() does memory allocation using GFP_KERNEL. that means - * this can deadlock when called a sc->gfp_mask that is not equal to - * GFP_KERNEL. + * We need to pass sc->gfp_mask to ttm_page_pool_free(). * * This code is crying out for a shrinker per pool.... */ @@ -408,7 +407,8 @@ ttm_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) if (shrink_pages == 0) break; pool = &_manager->pools[(i + pool_offset)%NUM_POOLS]; - shrink_pages = ttm_page_pool_free(pool, nr_free); + shrink_pages = ttm_page_pool_free(pool, nr_free, + sc->gfp_mask); freed += nr_free - shrink_pages; } mutex_unlock(&lock); @@ -710,7 +710,7 @@ static void ttm_put_pages(struct page **pages, unsigned npages, int flags, } spin_unlock_irqrestore(&pool->lock, irq_flags); if (npages) - ttm_page_pool_free(pool, npages); + ttm_page_pool_free(pool, npages, GFP_KERNEL); } /* @@ -850,7 +850,8 @@ void ttm_page_alloc_fini(void) ttm_pool_mm_shrink_fini(_manager); for (i = 0; i < NUM_POOLS; ++i) - ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES); + ttm_page_pool_free(&_manager->pools[i], FREE_ALL_PAGES, + GFP_KERNEL); kobject_put(&_manager->kobj); _manager = NULL; diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c index 524cc1a..ca65df1 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c @@ -411,8 +411,10 @@ static void ttm_dma_page_put(struct dma_pool *pool, struct dma_page *d_page) * * @pool: to free the pages from * @nr_free: If set to true will free all pages in pool + * @gfp: GFP flags. **/ -static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free) +static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free, + gfp_t gfp) { unsigned long irq_flags; struct dma_page *dma_p, *tmp; @@ -430,8 +432,7 @@ static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free) npages_to_free, nr_free); } #endif - pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), - GFP_KERNEL); + pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), gfp); if (!pages_to_free) { pr_err("%s: Failed to allocate memory for pool free operation\n", @@ -530,7 +531,7 @@ static void ttm_dma_free_pool(struct device *dev, enum pool_type type) if (pool->type != type) continue; /* Takes a spinlock.. */ - ttm_dma_page_pool_free(pool, FREE_ALL_PAGES); + ttm_dma_page_pool_free(pool, FREE_ALL_PAGES, GFP_KERNEL); WARN_ON(((pool->npages_in_use + pool->npages_free) != 0)); /* This code path is called after _all_ references to the * struct device has been dropped - so nobody should be @@ -983,7 +984,7 @@ void ttm_dma_unpopulate(struct ttm_dma_tt *ttm_dma, struct device *dev) /* shrink pool if necessary (only on !is_cached pools)*/ if (npages) - ttm_dma_page_pool_free(pool, npages); + ttm_dma_page_pool_free(pool, npages, GFP_KERNEL); ttm->state = tt_unpopulated; } EXPORT_SYMBOL_GPL(ttm_dma_unpopulate); @@ -993,10 +994,7 @@ EXPORT_SYMBOL_GPL(ttm_dma_unpopulate); * * XXX: (dchinner) Deadlock warning! * - * ttm_dma_page_pool_free() does GFP_KERNEL memory allocation, and so attention - * needs to be paid to sc->gfp_mask to determine if this can be done or not. - * GFP_KERNEL memory allocation in a GFP_ATOMIC reclaim context woul dbe really - * bad. + * We need to pass sc->gfp_mask to ttm_dma_page_pool_free(). * * I'm getting sadder as I hear more pathetical whimpers about needing per-pool * shrinkers @@ -1030,7 +1028,8 @@ ttm_dma_pool_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) if (++idx < pool_offset) continue; nr_free = shrink_pages; - shrink_pages = ttm_dma_page_pool_free(p->pool, nr_free); + shrink_pages = ttm_dma_page_pool_free(p->pool, nr_free, + sc->gfp_mask); freed += nr_free - shrink_pages; pr_debug("%s: (%s:%d) Asked to shrink %d, have %d more to go\n",