From patchwork Tue Feb 12 04:24:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Ga=C3=ABl_PORTAY?= X-Patchwork-Id: 10807317 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4CFCB13A4 for ; Tue, 12 Feb 2019 04:25:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3C1E828739 for ; Tue, 12 Feb 2019 04:25:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2FA322A7EC; Tue, 12 Feb 2019 04:25:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 6D30E28739 for ; Tue, 12 Feb 2019 04:25:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-Id:Date:Subject:To :From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=sTLJOAvrZewBrkctDrFHTIL4mmOrWef3WUy8gDVfuL8=; b=UGouBG9w/UVWu/ mrannjaBhpre6qsG6e977dgBikIyc4s7bmLxSUfkxdX5KrrWpd0sdRXDr0bC/XNke5jjZKfX+Jzju nLzp2ZjIKTeGJ6Jt3u7mEZ7BoyRA5VTG3trPRN6rvnjfJE3nJLgSG2ma5ZCpo+xj4iKWY5/pf37Cm MJ6G3o1IZWST5U88VFqD+bMktefK2UqWFgOv/AQsg7tSW88Zi7UEcq/gEpMup4o1TcrBz0+0IWmau LMxuX9eLuDXHqh4rLh6zWBx8HctgbvyXxpLbrVGPT6zPaQjByDR2aJ8EeY0l3PjraQA7Kfa0kS9Ko hg5ZnH/+UmgbMZfwZYcQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gtPdA-0003Wl-Ge; Tue, 12 Feb 2019 04:25:12 +0000 Received: from bhuna.collabora.co.uk ([46.235.227.227]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1gtPd5-0002Zb-Q8 for linux-arm-kernel@lists.infradead.org; Tue, 12 Feb 2019 04:25:10 +0000 Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: gportay) with ESMTPSA id 92701260499 From: =?utf-8?q?Ga=C3=ABl_PORTAY?= To: linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org, Gabriel Krisman Bertazi Subject: [PATCH] ARM: dma-mapping: prevent writeback deadlock in CMA allocator Date: Mon, 11 Feb 2019 23:24:58 -0500 Message-Id: <20190212042458.31856-1-gael.portay@collabora.com> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190211_202508_123357_49134D16 X-CRM114-Status: GOOD ( 12.80 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Laura Abbott , kernel@collabora.com, =?utf-8?q?Ga?= =?utf-8?q?=C3=ABl_PORTAY?= , Mike Kravetz Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP A deadlock happens when a task initiates a CMA allocation that triggers a page migration *AND* the tasks holding the subsequent pages have to writeback their pages using CMA allocations. In such a situation, the task that has triggered the page migration holds a mutex that prevents other tasks from migrating their pages using that same CMA allocator. This leads to a deadlock. The CMA is incapable of honoring the NOIO flags in some scenario, thus cannot be used for writeback. The fix allows the code that chooses which allocator to use in the ARM platform to avoid the CMA case for that scenario. The ARM DMA layer checks for allow blocking flag (__GFP_DIRECT_RECLAIM) to decide whether to go for CMA or not. That test is not sufficient to cover the case of writeback (GFP_NOIO). The fix consists in adding a gfp_allow_writeback helper that tests for the __GFP_IO flag. Then, the DMA layer uses it to decide not to go for CMA in case of writeback. Fixes: QSGRenderThread D 0 1852 564 0x00000000 Backtrace: [] (__schedule) from [] (schedule+0x5c/0xcc) r10:c0f04068 r9:efc2e600 r8:ffffe000 r7:00004000 r6:efc2e600 r5:edd31a94 r4:ffffe000 [] (schedule) from [] (io_schedule+0x20/0x48) r5:edd31a94 r4:00000000 [] (io_schedule) from [] (wait_on_page_bit+0x10c/0x158) r5:edd31a94 r4:c0f04064 [] (wait_on_page_bit) from [] (migrate_pages+0x658/0x8e0) r10:efc2e600 r9:00000000 r8:00000000 r7:00000000 r6:ef899260 r5:ea733c7c r4:efc2e5e0 [] (migrate_pages) from [] (alloc_contig_range+0x17c/0x3b0) r10:00071700 r9:c026c21c r8:00071b31 r7:00071b60 r6:ffffe000 r5:00000000 r4:edd31b54 [] (alloc_contig_range) from [] (cma_alloc+0x110/0x2f4) r10:00000460 r9:00020000 r8:fffffff4 r7:00000460 r6:c0fe0444 r5:00071700 r4:00001700 [] (cma_alloc) from [] (dma_alloc_from_contiguous+0x44/0x4c) r10:ecfe4840 r9:00000460 r8:00000647 r7:edd31cb4 r6:ec217c10 r5:00000001 r4:00460000 [] (dma_alloc_from_contiguous) from [] (__alloc_from_contiguous+0x58/0xf8) [] (__alloc_from_contiguous) from [] (cma_allocator_alloc+0x50/0x58) r10:ecfe4840 r9:eccfbd58 r8:c0f04d08 r7:00000000 r6:ffffffff r5:ec217c10 r4:006002c0 [] (cma_allocator_alloc) from [] (__dma_alloc+0x1e0/0x308) r5:ec217c10 r4:006002c0 [] (__dma_alloc) from [] (arm_dma_alloc+0x4c/0x58) r10:edd31e24 r9:eccfbd58 r8:c0f04d08 r7:c011a38c r6:ec217c10 r5:00000000 r4:00000004 [] (arm_dma_alloc) from [] (drm_gem_cma_create+0xd0/0x168) r5:eccfbcc0 r4:00460000 [] (drm_gem_cma_create) from [] (drm_gem_cma_dumb_create+0x50/0xa4) r9:c05ad874 r8:00000010 r7:00000000 r6:00000000 r5:ecd9c500 r4:edd31e34 [] (drm_gem_cma_dumb_create) from [] (drm_mode_create_dumb+0xbc/0xd0) r7:00000000 r6:00000000 r5:00000000 r4:00460000 [] (drm_mode_create_dumb) from [] (drm_mode_create_dumb_ioctl+0x18/0x1c) r7:00000000 r6:c0f04d08 r5:ec559000 r4:ecd9c500 [] (drm_mode_create_dumb_ioctl) from [] (drm_ioctl_kernel+0x90/0xec) [] (drm_ioctl_kernel) from [] (drm_ioctl+0x2c4/0x3e4) r10:c0f04d08 r9:edd31e24 r8:000000b2 r7:c02064b2 r6:ecd9c500 r5:00000020 r4:c0a47ac8 [] (drm_ioctl) from [] (do_vfs_ioctl+0xac/0x934) r10:00000036 r9:0000001a r8:ec554b90 r7:c02064b2 r6:ed0d3d80 r5:ac5df5d8 r4:c0f04d08 [] (do_vfs_ioctl) from [] (ksys_ioctl+0x44/0x68) r10:00000036 r9:edd30000 r8:ac5df5d8 r7:c02064b2 r6:0000001a r5:ed0d3d80 r4:ed0d3d81 [] (ksys_ioctl) from [] (sys_ioctl+0x18/0x1c) r9:edd30000 r8:c0101204 r7:00000036 r6:c02064b2 r5:ac5df5d8 r4:ac5df640 [] (sys_ioctl) from [] (ret_fast_syscall+0x0/0x54) Exception stack(0xedd31fa8 to 0xedd31ff0) 1fa0: ac5df640 ac5df5d8 0000001a c02064b2 ac5df5d8 00000005 1fc0: ac5df640 ac5df5d8 c02064b2 00000036 00000380 0188cfc0 ac5df640 ac5df60c 1fe0: b4bd0094 ac5df5b4 b4bb7bb4 b55444fc usb-storage D 0 349 2 0x00000000 Backtrace: [] (__schedule) from [] (schedule+0x5c/0xcc) r10:00000002 r9:00020000 r8:c0f20b34 r7:00000000 r6:ece579a4 r5:ffffe000 r4:ffffe000 [] (schedule) from [] (schedule_preempt_disabled+0x30/0x4c) r5:ffffe000 r4:ffffe000 [] (schedule_preempt_disabled) from [] (__mutex_lock.constprop.7+0x2f8/0x60c) r5:ffffe000 r4:c0f20b30 [] (__mutex_lock.constprop.7) from [] (__mutex_lock_slowpath+0x1c/0x20) r10:00000001 r9:00020000 r8:fffffff4 r7:00000001 r6:c0fe0444 r5:00070068 r4:00000068 [] (__mutex_lock_slowpath) from [] (mutex_lock+0x50/0x54) [] (mutex_lock) from [] (cma_alloc+0xfc/0x2f4) [] (cma_alloc) from [] (dma_alloc_from_contiguous+0x44/0x4c) r10:ed19e5c0 r9:00000001 r8:00000647 r7:ece57aec r6:ec215610 r5:00000001 r4:00001000 [] (dma_alloc_from_contiguous) from [] (__alloc_from_contiguous+0x58/0xf8) [] (__alloc_from_contiguous) from [] (cma_allocator_alloc+0x50/0x58) r10:ed19e5c0 r9:ed19e84c r8:c0f04d08 r7:00000000 r6:ffffffff r5:ec215610 r4:00600000 [] (cma_allocator_alloc) from [] (__dma_alloc+0x1e0/0x308) r5:ec215610 r4:00600000 [] (__dma_alloc) from [] (arm_dma_alloc+0x4c/0x58) r10:c011a38c r9:ec215610 r8:c0f04d08 r7:00600000 r6:ece6c808 r5:00000000 r4:00000000 [] (arm_dma_alloc) from [] (dma_pool_alloc+0x21c/0x290) r5:ece6c800 r4:ed19e840 [] (dma_pool_alloc) from [] (ehci_qtd_alloc+0x30/0x94 [ehci_hcd]) r10:00000200 r9:000000ca r8:e72e0260 r7:ece57c6c r6:f15c6f60 r5:c0f04d08 r4:00000200 [] (ehci_qtd_alloc [ehci_hcd]) from [] (qh_urb_transaction+0x150/0x42c [ehci_hcd]) r6:f15c6f60 r5:00019400 r4:00000200 [] (qh_urb_transaction [ehci_hcd]) from [] (ehci_urb_enqueue+0x74/0xe3c [ehci_hcd]) r10:000000ef r9:eccd8c00 r8:ed236308 r7:ed236300 r6:00000000 r5:ece57c6c r4:00000003 [] (ehci_urb_enqueue [ehci_hcd]) from [] (usb_hcd_submit_urb+0xc8/0x980 [usbcore]) r10:000000ef r9:00600000 r8:ed236308 r7:c0f04d08 r6:00000000 r5:eccd8c00 r4:ed236300 [] (usb_hcd_submit_urb [usbcore]) from [] (usb_submit_urb+0x360/0x564 [usbcore]) r10:000000ef r9:bf1d8924 r8:00000000 r7:00600000 r6:00000002 r5:eccc1800 r4:ed236300 [] (usb_submit_urb [usbcore]) from [] (usb_sg_wait+0x68/0x154 [usbcore]) r10:0000001f r9:00000000 r8:00000001 r7:eca5951c r6:c0008200 r5:00000000 r4:eca59514 [] (usb_sg_wait [usbcore]) from [] (usb_stor_bulk_transfer_sglist.part.2+0x80/0xdc [usb_storage]) r9:0001e000 r8:eca594ac r7:0001e000 r6:c0008200 r5:eca59514 r4:eca59488 [] (usb_stor_bulk_transfer_sglist.part.2 [usb_storage]) from [] (usb_stor_bulk_srb+0x4c/0x7c [usb_storage]) r8:c0f04d08 r7:00000000 r6:ed71f0c0 r5:c0f04d08 r4:ed71f0c0 [] (usb_stor_bulk_srb [usb_storage]) from [] (usb_stor_Bulk_transport+0x120/0x390 [usb_storage]) r5:f19e2000 r4:eca59488 [] (usb_stor_Bulk_transport [usb_storage]) from [] (usb_stor_invoke_transport+0x3c/0x490 [usb_storage]) r10:ecd0bb3c r9:c0f03d00 r8:c0f04d08 r7:ed71f0c0 r6:c0f04d08 r5:ed71f0c0 r4:eca59488 [] (usb_stor_invoke_transport [usb_storage]) from [] (usb_stor_transparent_scsi_command+0x18/0x1c [usb_storage]) r10:ecd0bb3c r9:c0f03d00 r8:c0f04d08 r7:ed71f0c0 r6:00000000 r5:eca59550 r4:eca59488 [] (usb_stor_transparent_scsi_command [usb_storage]) from [] (usb_stor_control_thread+0x174/0x29c [usb_storage]) [] (usb_stor_control_thread [usb_storage]) from [] (kthread+0x154/0x16c) r10:ecd0bb3c r9:bf2bf470 r8:eca59488 r7:ece56000 r6:ed1f4f80 r5:ecba3140 r4:00000000 [] (kthread) from [] (ret_from_fork+0x14/0x2c) Exception stack(0xece57fb0 to 0xece57ff8) 7fa0: 00000000 00000000 00000000 00000000 7fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 7fe0: 00000000 00000000 00000000 00000000 00000013 00000000 r10:00000000 r9:00000000 r8:00000000 r7:00000000 r6:00000000 r5:c0149e70 r4:ed1f4f80 Cc: Laura Abbott Cc: Mike Kravetz Signed-off-by: Gaƫl PORTAY --- Hi, I am suggesting this patch after the discussion on that thread[1]. Regards, Gael [1]: https://marc.info/?l=linux-mm&m=154750965506335&w=2 arch/arm/mm/dma-mapping.c | 5 +++-- include/linux/gfp.h | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index f1e2922e447c..98479b6bb425 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -725,7 +725,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, u64 mask = get_coherent_dma_mask(dev); struct page *page = NULL; void *addr; - bool allowblock, cma; + bool allowblock, allowwriteback, cma; struct arm_dma_buffer *buf; struct arm_dma_alloc_args args = { .dev = dev, @@ -769,7 +769,8 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, *handle = DMA_MAPPING_ERROR; allowblock = gfpflags_allow_blocking(gfp); - cma = allowblock ? dev_get_cma_area(dev) : false; + allowwriteback = gfpflags_allow_writeback(gfp); + cma = (allowblock && !allowwriteback) ? dev_get_cma_area(dev) : false; if (cma) buf->allocator = &cma_allocator; diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 5f5e25fd6149..70d7c598eb21 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -325,6 +325,11 @@ static inline bool gfpflags_allow_blocking(const gfp_t gfp_flags) return !!(gfp_flags & __GFP_DIRECT_RECLAIM); } +static inline bool gfpflags_allow_writeback(const gfp_t gfp_flags) +{ + return !!(gfp_flags & __GFP_IO); +} + #ifdef CONFIG_HIGHMEM #define OPT_ZONE_HIGHMEM ZONE_HIGHMEM #else