From patchwork Mon Jan 9 07:30:02 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikita Yushchenko X-Patchwork-Id: 9504159 X-Patchwork-Delegate: horms@verge.net.au Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 63D0860710 for ; Mon, 9 Jan 2017 07:30:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5218C2582C for ; Mon, 9 Jan 2017 07:30:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 43EE12840E; Mon, 9 Jan 2017 07:30:25 +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=-6.4 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 322E22582C for ; Mon, 9 Jan 2017 07:30:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1761647AbdAIHaR (ORCPT ); Mon, 9 Jan 2017 02:30:17 -0500 Received: from mail-lf0-f47.google.com ([209.85.215.47]:35888 "EHLO mail-lf0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1761836AbdAIHaM (ORCPT ); Mon, 9 Jan 2017 02:30:12 -0500 Received: by mail-lf0-f47.google.com with SMTP id o140so34081166lff.3 for ; Sun, 08 Jan 2017 23:30:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cogentembedded-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id; bh=kep6S/hqoBQ7MefqnlsBEu/hrZVMkS7b/2yvJUV00lY=; b=IOrhudrw2TMqDMHgBO+Kx6W4mD8zRDsmEe6QE809LeT/AdsPoZlqFRXL6n9KqUYK6u wIp0AiaOXpQCAWeoxt/2VnPqjvWyesLDD3iEk0K23r8jTPPw3N0aDmdcxbtnYk+3FUM5 roi18ObR26AyVMDyVYiWZ/vZSRgnYDn6JwTN6Js8YfFeqdv+ZIO6aeXiRUqGYIfdYrAj 5SGNTgx01qT/cSxtMq5/lVCRms58H7yBgerdjxV76VLo1I5bgDuDYfJB653YYygDtC1N 8F2KbXLnqWEDeNH66AmY08GKm+gDidYzhUjjj9/72wDEzFAleSlal+9eZcQzjaVAD7C1 rudg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=kep6S/hqoBQ7MefqnlsBEu/hrZVMkS7b/2yvJUV00lY=; b=KY77l/2maOdsZNlXQYARiR3PJwNippaq2g6wzStOcGC0VmvkF+9njo9Vq96ewEsnw1 Nqv5MWKks0tOb28ERUJTGqvDXDMsrPnIO2zymDGYeQSqhaEiSYixE+set/7/PL+7Mn6b toEz5iEHaCfP0h87Ge/h54H0DtOGXfuhZmHspyMWPbuX+WCZIt3XU3zWs80C3azR6KHa Po9Mia84CSxvfFYO70b9PeDEmtpgetycGFo3/y6rFeyMaU2VSigaf1T1Q9Huk40eXkKk DX38qbRnqriZk+1y+34tWdgb4LBGQYkDtSQ+zC0o7FhRTmTzMZUj3YThBaokY4mLkZJj l05g== X-Gm-Message-State: AIkVDXI88VnAO9RiRQ9t0t1f8Qo+/r1nPWXli+HInmn1O7YewsCilhE5AB6BZ584af7vkg== X-Received: by 10.25.40.211 with SMTP id o202mr32861007lfo.183.1483947010625; Sun, 08 Jan 2017 23:30:10 -0800 (PST) Received: from hugenb.home (nikaet.starlink.ru. [94.141.168.29]) by smtp.gmail.com with ESMTPSA id d79sm21421937lfd.46.2017.01.08.23.30.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 08 Jan 2017 23:30:09 -0800 (PST) From: Nikita Yushchenko To: Arnd Bergmann Cc: linux-arm-kernel@lists.infradead.org, Will Deacon , Catalin Marinas , linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org, Simon Horman , Bjorn Helgaas , artemi.ivanov@cogentembedded.com, Nikita Yushchenko Subject: [PATCH v2] arm64: do not set dma masks that device connection can't handle Date: Mon, 9 Jan 2017 10:30:02 +0300 Message-Id: <1483947002-16410-1-git-send-email-nikita.yoush@cogentembedded.com> X-Mailer: git-send-email 2.1.4 Sender: linux-renesas-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP It is possible that device is capable of 64-bit DMA addresses, and device driver tries to set wide DMA mask, but bridge or bus used to connect device to the system can't handle wide addresses. With swiotlb, memory above 4G still can be used by drivers for streaming DMA, but *dev->mask and dev->dma_coherent_mask must still keep values that hardware handles physically. This patch enforces that. Based on original version by Arnd Bergmann , extended with coherent mask hadnling. Signed-off-by: Nikita Yushchenko CC: Arnd Bergmann --- Changes since v1: - fixed issues noted by Sergei Shtylyov - save mask, not size - remove doube empty line arch/arm64/Kconfig | 3 +++ arch/arm64/include/asm/device.h | 1 + arch/arm64/mm/dma-mapping.c | 51 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 1117421..afb2c08 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -216,6 +216,9 @@ config NEED_DMA_MAP_STATE config NEED_SG_DMA_LENGTH def_bool y +config ARCH_HAS_DMA_SET_COHERENT_MASK + def_bool y + config SMP def_bool y diff --git a/arch/arm64/include/asm/device.h b/arch/arm64/include/asm/device.h index 243ef25..a57e7bb 100644 --- a/arch/arm64/include/asm/device.h +++ b/arch/arm64/include/asm/device.h @@ -22,6 +22,7 @@ struct dev_archdata { void *iommu; /* private IOMMU data */ #endif bool dma_coherent; + u64 parent_dma_mask; }; struct pdev_archdata { diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index e040827..5ab15ce 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c @@ -352,6 +352,30 @@ static int __swiotlb_dma_supported(struct device *hwdev, u64 mask) return 1; } +static int __swiotlb_set_dma_mask(struct device *dev, u64 mask) +{ + /* device is not DMA capable */ + if (!dev->dma_mask) + return -EIO; + + /* mask is below swiotlb bounce buffer, so fail */ + if (!swiotlb_dma_supported(dev, mask)) + return -EIO; + + /* + * because of the swiotlb, we can return success for + * larger masks, but need to ensure that bounce buffers + * are used above parent_dma_mask, so set that as + * the effective mask. + */ + if (mask > dev->archdata.parent_dma_mask) + mask = dev->archdata.parent_dma_mask; + + *dev->dma_mask = mask; + + return 0; +} + static struct dma_map_ops swiotlb_dma_ops = { .alloc = __dma_alloc, .free = __dma_free, @@ -367,8 +391,23 @@ static struct dma_map_ops swiotlb_dma_ops = { .sync_sg_for_device = __swiotlb_sync_sg_for_device, .dma_supported = __swiotlb_dma_supported, .mapping_error = swiotlb_dma_mapping_error, + .set_dma_mask = __swiotlb_set_dma_mask, }; +int dma_set_coherent_mask(struct device *dev, u64 mask) +{ + if (!dma_supported(dev, mask)) + return -EIO; + + if (get_dma_ops(dev) == &swiotlb_dma_ops && + mask > dev->archdata.parent_dma_mask) + mask = dev->archdata.parent_dma_mask; + + dev->coherent_dma_mask = mask; + return 0; +} +EXPORT_SYMBOL(dma_set_coherent_mask); + static int __init atomic_pool_init(void) { pgprot_t prot = __pgprot(PROT_NORMAL_NC); @@ -958,6 +997,18 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, if (!dev->archdata.dma_ops) dev->archdata.dma_ops = &swiotlb_dma_ops; + /* + * we don't yet support buses that have a non-zero mapping. + * Let's hope we won't need it + */ + WARN_ON(dma_base != 0); + + /* + * Whatever the parent bus can set. A device must not set + * a DMA mask larger than this. + */ + dev->archdata.parent_dma_mask = size - 1; + dev->archdata.dma_coherent = coherent; __iommu_setup_dma_ops(dev, dma_base, size, iommu); }