Received: by 2002:ac0:a581:0:0:0:0:0 with SMTP id m1-v6csp1133957imm; Tue, 3 Jul 2018 06:10:43 -0700 (PDT) X-Google-Smtp-Source: ADUXVKJj8aU/gKR7/2vARMH7AnNm8PHlwMbsgfg902ybbX7+JS0PtzHzuBZvXHTWgHRB7ByQQIYw X-Received: by 2002:a63:a401:: with SMTP id c1-v6mr25478741pgf.147.1530623443686; Tue, 03 Jul 2018 06:10:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1530623443; cv=none; d=google.com; s=arc-20160816; b=qpjII6bWjrPLLrLn8M344eVCDwzgm64SSqiTOpvpqWj1gtYuQ1iQY/iVpEpdeqOZFp xiR6ivt73tvRG/bdq/v7Tlcq58YcijW1EM0ZHDFt3OHxF3jULGRfQmzki8VTLdOpVJrJ s4kq0XZdHUqshZBAyRHR0rnqF1KRojIJ2PlkpzanF2EjwO2+4CP/n2D+fghV9pNRUdah I+0vbvFFdG1V/VntW796gMPDnYrECdkMalle56JmgLICljCiieboq96E1lTtcNI0k3Ul 9YY3EKiepylqS5mA4oR1A03TYIma6j3fPAEIsKtRkdFHoHl76V0QFvhy/Dyh3Siib3JK QkVA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :arc-authentication-results; bh=5yfzfxcDRGFMc9EBVhUfJrfCqukzhx6VlbgvnTWfur4=; b=yT2HfearnBdYzqR2US/nSrUi9YGkjmP9WqNgQC0IvlWTxt7+y99FPWhbHNg5/zM3sp EkYwriOOin2dp9e8QVh8Gzr1ICKaQ3+wz2Ki0NABmyxuEDEcm9PlRuji4q/ctpBwgS25 G5GglqmCbgvaZ0ueOJapRME/8uKTccKdOiZ/7pyQUttTInH+qJY1O6F10oVqY2T6/ARj 2+CxH5GDLFBi/dMefXL87igM05M80rv205sKh9RPtGH/FayRbhv+COHGySvna56dwU3W U9U475FoPyoX/eOejrzB/1HwzBz9pIzNs9HVTSOiznYAsYZe8GKl4iz6ipzHgcS+eNZP eK9g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id k91-v6si1099310pld.248.2018.07.03.06.10.22; Tue, 03 Jul 2018 06:10:43 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753397AbeGCNIh (ORCPT + 99 others); Tue, 3 Jul 2018 09:08:37 -0400 Received: from foss.arm.com ([217.140.101.70]:48916 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752606AbeGCNIg (ORCPT ); Tue, 3 Jul 2018 09:08:36 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id BEB3A80D; Tue, 3 Jul 2018 06:08:35 -0700 (PDT) Received: from e110467-lin.cambridge.arm.com (e110467-lin.cambridge.arm.com [10.1.210.23]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 8D4FE3F5BA; Tue, 3 Jul 2018 06:08:34 -0700 (PDT) From: Robin Murphy To: hch@lst.de, m.szyprowski@samsung.com Cc: iommu@lists.linux-foundation.org, linux-kernel@vger.kernel.org, noring@nocrew.org, JuergenUrban@gmx.de Subject: [PATCH] dma-mapping: Relax warnings for per-device areas Date: Tue, 3 Jul 2018 14:08:30 +0100 Message-Id: <1f8262d206c6886072d04cc93454f6e3f812bd20.1530623284.git.robin.murphy@arm.com> X-Mailer: git-send-email 2.17.1.dirty Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The reasons why dma_free_attrs() should not be called from IRQ context are not necessarily obvious and somewhat buried in the development history, so let's start by documenting the warning itself to help anyone who does happen to hit it and wonder what the deal is. However, this check turns out to be slightly over-restrictive for the way that per-device memory has been spliced into the general API, since for that case we know that dma_declare_coherent_memory() has created an appropriate CPU mapping for the entire area and nothing dynamic should be happening. Given that the usage model for per-device memory is often more akin to streaming DMA than 'real' coherent DMA (e.g. allocating and freeing space to copy short-lived packets in and out), it is also somewhat more reasonable for those operations to happen in IRQ handlers for such devices. A somewhat similar line of reasoning also applies at the other end for the mask check in dma_alloc_attrs() too - indeed, a device which cannot access anything other than its own local memory probably *shouldn't* have a valid mask for the general coherent DMA API. Therefore, let's move the per-device area hooks up ahead of the assorted checks, so that they get a chance to resolve the request before we get as far as definite "you're doing it wrong" territory. Reported-by: Fredrik Noring Signed-off-by: Robin Murphy --- include/linux/dma-mapping.h | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index f9cc309507d9..ffeca3ab59c0 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -512,12 +512,12 @@ static inline void *dma_alloc_attrs(struct device *dev, size_t size, const struct dma_map_ops *ops = get_dma_ops(dev); void *cpu_addr; - BUG_ON(!ops); - WARN_ON_ONCE(dev && !dev->coherent_dma_mask); - if (dma_alloc_from_dev_coherent(dev, size, dma_handle, &cpu_addr)) return cpu_addr; + BUG_ON(!ops); + WARN_ON_ONCE(dev && !dev->coherent_dma_mask); + /* let the implementation decide on the zone to allocate from: */ flag &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM); @@ -537,12 +537,19 @@ static inline void dma_free_attrs(struct device *dev, size_t size, { const struct dma_map_ops *ops = get_dma_ops(dev); - BUG_ON(!ops); - WARN_ON(irqs_disabled()); - if (dma_release_from_dev_coherent(dev, get_order(size), cpu_addr)) return; + BUG_ON(!ops); + /* + * On non-coherent platforms which implement DMA-coherent buffers via + * non-cacheable remaps, ops->free() may call vunmap(). Thus arriving + * here in IRQ context is a) at risk of a BUG_ON() or trying to sleep + * on some machines, and b) an indication that the driver is probably + * misusing the coherent API anyway. + */ + WARN_ON(irqs_disabled()); + if (!ops->free || !cpu_addr) return; -- 2.17.1.dirty