From patchwork Fri Feb 19 08:22:42 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 8357781 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 94A56C0553 for ; Fri, 19 Feb 2016 08:25:27 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 733A420411 for ; Fri, 19 Feb 2016 08:25:26 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5444E2038D for ; Fri, 19 Feb 2016 08:25:25 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1aWgLf-0002pV-Ud; Fri, 19 Feb 2016 08:23:35 +0000 Received: from mailout3.w1.samsung.com ([210.118.77.13]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1aWgLS-0002l7-GW for linux-arm-kernel@lists.infradead.org; Fri, 19 Feb 2016 08:23:23 +0000 Received: from eucpsbgm1.samsung.com (unknown [203.254.199.244]) by mailout3.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0O2S00CCKCMB9D90@mailout3.w1.samsung.com> for linux-arm-kernel@lists.infradead.org; Fri, 19 Feb 2016 08:22:59 +0000 (GMT) X-AuditID: cbfec7f4-f79026d00000418a-af-56c6d0e24c43 Received: from eusync3.samsung.com ( [203.254.199.213]) by eucpsbgm1.samsung.com (EUCPMTA) with SMTP id 71.BF.16778.2E0D6C65; Fri, 19 Feb 2016 08:22:58 +0000 (GMT) Received: from amdc1339.digital.local ([106.116.147.30]) by eusync3.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0O2S00GAZCM67900@eusync3.samsung.com>; Fri, 19 Feb 2016 08:22:58 +0000 (GMT) From: Marek Szyprowski To: iommu@lists.linux-foundation.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [RFC 1/3] drm/exynos: rewrite IOMMU support code Date: Fri, 19 Feb 2016 09:22:42 +0100 Message-id: <1455870164-25337-2-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.9.2 In-reply-to: <1455870164-25337-1-git-send-email-m.szyprowski@samsung.com> References: <1455870164-25337-1-git-send-email-m.szyprowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFmpikeLIzCtJLcpLzFFi42I5/e/4Vd1HF46FGVx9ZGHxd9IxdouNM9az Wrxf1sNoceXrezaL/49es1pMuj+BxWLBfmuLztkb2C1evzC06Jy4hN3iy5WHTBabHl9jtbi8 aw6bxe3LvBZrj9xlt9gx5QCTxcEPT1gtzuxfyWbxufUfm8XLjydYHEQ8nhycx+SxZt4aRo+W 5h42j9+/JjF6zG64yOIxu2Mmq8fhrwtZPO53H2fy2Lyk3uP2v8fMHpNvLGf0+DtrP4tH35ZV jB7br81j9vi8SS6AP4rLJiU1J7MstUjfLoEr4+Cp02wFWy0qFkw+zNbA2KrfxcjBISFgIjG/ T72LkRPIFJO4cG89WxcjF4eQwFJGiQWXj7KCJIQEmpgkbu43BbHZBAwlut52sYHYIgJZEvvv b2QCaWAW2Moq8bplPSNIQljAUuLDkRvsIDaLgKrEzU2LwAbxCnhIfNo3jRVim5zE/5crmEBs TgFPidOvl7FBLPOQ+H93GfMERt4FjAyrGEVTS5MLipPScw31ihNzi0vz0vWS83M3MUJi5ssO xsXHrA4xCnAwKvHwXjA4FibEmlhWXJl7iFGCg1lJhFfXHyjEm5JYWZValB9fVJqTWnyIUZqD RUmcd+6u9yFCAumJJanZqakFqUUwWSYOTqkGxnl6J9Ztrvx3cNrzy3/+Fn498OKiioPC202v gmSn9K+VEkz5tkfvVvL3ra/Lg9uOuzV8MtHondnqUBKrvmFT9//lN/zO3q89tyqKN2mNel5g V2T3TueZ4ZnW3eeyjb60KKvX1U3e+a1JbO9C1R9667Jn297M8FeMkzwuVMCRat5yWj744+rr V5VYijMSDbWYi4oTAV7gPviVAgAA X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160219_002322_750256_6D15FFB5 X-CRM114-Status: GOOD ( 23.61 ) X-Spam-Score: -6.9 (------) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Inki Dae , Krzysztof Kozlowski , Russell King - ARM Linux , Heiko Stuebner , Arnd Bergmann , Bartlomiej Zolnierkiewicz , Catalin Marinas , Joerg Roedel , Will Deacon , dri-devel@lists.freedesktop.org, Tomasz Figa , linaro-mm-sig@lists.linaro.org, Sakari Ailus , Laurent Pinchart , Mark Yao , Robin Murphy , Marek Szyprowski MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, 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 This patch replaces usage of ARM-specific IOMMU/DMA-mapping related calls with new generic code for managing DMA-IOMMU integration layer. It also removes all the hacks, which were needed to configure common DMA/IO address space on the virtual exynos-drm device. Since moving Exynos GEM code to use on of real devices for DMA-mapping operations, such hacks are no longer needed. The only requirement is to have all the devices, which build Exynos DRM, attached to the same IOMMU domain (to share IO address space). Signed-off-by: Marek Szyprowski --- drivers/gpu/drm/exynos/Kconfig | 2 +- drivers/gpu/drm/exynos/exynos_drm_drv.c | 7 +-- drivers/gpu/drm/exynos/exynos_drm_drv.h | 2 +- drivers/gpu/drm/exynos/exynos_drm_iommu.c | 91 +++++++++++++++++++------------ drivers/gpu/drm/exynos/exynos_drm_iommu.h | 2 +- 5 files changed, 59 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 83efca941388..b0d0aaa7fea5 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -15,7 +15,7 @@ if DRM_EXYNOS config DRM_EXYNOS_IOMMU bool - depends on EXYNOS_IOMMU && ARM_DMA_USE_IOMMU + depends on EXYNOS_IOMMU && IOMMU_DMA default y comment "CRTCs" diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index c7fce7ffeef5..45aa480f1890 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -159,12 +159,7 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags) DRM_INFO("Exynos DRM: using %s device for DMA mapping operations\n", dev_name(private->dma_dev)); - /* - * create mapping to manage iommu table and set a pointer to iommu - * mapping structure to iommu_mapping of private data. - * also this iommu_mapping can be used to check if iommu is supported - * or not. - */ + /* create common IOMMU mapping for all devices attached to Exynos DRM */ ret = drm_create_iommu_mapping(dev); if (ret < 0) { DRM_ERROR("failed to create iommu mapping.\n"); diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 303056311c0c..b107f77d0897 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -222,7 +222,7 @@ struct exynos_drm_private { struct device *dma_dev; unsigned long da_start; unsigned long da_space_size; - void *mapping; + struct iommu_domain *domain; unsigned int pipe; diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.c b/drivers/gpu/drm/exynos/exynos_drm_iommu.c index 146ac88078ae..89e51ed6499d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_iommu.c +++ b/drivers/gpu/drm/exynos/exynos_drm_iommu.c @@ -14,13 +14,28 @@ #include #include -#include - -#include +#include #include "exynos_drm_drv.h" #include "exynos_drm_iommu.h" +static inline int configure_dma_max_seg_size(struct device *dev) +{ + if (!dev->dma_parms) + dev->dma_parms = kzalloc(sizeof(*dev->dma_parms), GFP_KERNEL); + if (!dev->dma_parms) + return -ENOMEM; + + dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); + return 0; +} + +static inline void clear_dma_max_seg_size(struct device *dev) +{ + kfree(dev->dma_parms); + dev->dma_parms = NULL; +} + /* * drm_create_iommu_mapping - create a mapping structure * @@ -28,38 +43,48 @@ */ int drm_create_iommu_mapping(struct drm_device *drm_dev) { - struct dma_iommu_mapping *mapping = NULL; struct exynos_drm_private *priv = drm_dev->dev_private; + struct device *dev = to_dma_dev(drm_dev); + int ret; if (!priv->da_start) priv->da_start = EXYNOS_DEV_ADDR_START; if (!priv->da_space_size) priv->da_space_size = EXYNOS_DEV_ADDR_SIZE; - mapping = arm_iommu_create_mapping(&platform_bus_type, priv->da_start, - priv->da_space_size); + priv->domain = iommu_domain_alloc(dev->bus); + if (!priv->domain) + return -ENOMEM; - if (IS_ERR(mapping)) - return PTR_ERR(mapping); + ret = iommu_get_dma_cookie(priv->domain); + if (ret) + goto free_domain; - priv->mapping = mapping; + ret = iommu_dma_init_domain(priv->domain, priv->da_start, + priv->da_space_size); + if (ret) + goto put_cookie; return 0; + +put_cookie: + iommu_put_dma_cookie(priv->domain); +free_domain: + iommu_domain_free(priv->domain); + return ret; } /* * drm_release_iommu_mapping - release iommu mapping structure * * @drm_dev: DRM device - * - * if mapping->kref becomes 0 then all things related to iommu mapping - * will be released */ void drm_release_iommu_mapping(struct drm_device *drm_dev) { struct exynos_drm_private *priv = drm_dev->dev_private; - arm_iommu_release_mapping(priv->mapping); + iommu_put_dma_cookie(priv->domain); + iommu_domain_free(priv->domain); } /* @@ -75,29 +100,25 @@ int drm_iommu_attach_device(struct drm_device *drm_dev, struct device *subdrv_dev) { struct exynos_drm_private *priv = drm_dev->dev_private; + struct device *dev = to_dma_dev(drm_dev); + struct iommu_domain *domain = priv->domain; int ret; - if (!priv->mapping) - return 0; - - subdrv_dev->dma_parms = devm_kzalloc(subdrv_dev, - sizeof(*subdrv_dev->dma_parms), - GFP_KERNEL); - if (!subdrv_dev->dma_parms) - return -ENOMEM; - - dma_set_max_seg_size(subdrv_dev, 0xffffffffu); - - if (subdrv_dev->archdata.mapping) - arm_iommu_detach_device(subdrv_dev); + if (get_dma_ops(dev) != get_dma_ops(subdrv_dev)) { + DRM_ERROR("Device %s lacks support for IOMMU\n", + dev_name(subdrv_dev)); + return -EINVAL; + } - ret = arm_iommu_attach_device(subdrv_dev, priv->mapping); - if (ret < 0) { - DRM_DEBUG_KMS("failed iommu attach.\n"); + ret = configure_dma_max_seg_size(subdrv_dev); + if (ret) return ret; - } - return 0; + ret = iommu_attach_device(domain, subdrv_dev); + if (ret != 0) + clear_dma_max_seg_size(subdrv_dev); + + return ret; } /* @@ -113,10 +134,8 @@ void drm_iommu_detach_device(struct drm_device *drm_dev, struct device *subdrv_dev) { struct exynos_drm_private *priv = drm_dev->dev_private; - struct dma_iommu_mapping *mapping = priv->mapping; - - if (!mapping || !mapping->domain) - return; + struct iommu_domain *domain = priv->domain; - arm_iommu_detach_device(subdrv_dev); + iommu_detach_device(domain, subdrv_dev); + clear_dma_max_seg_size(subdrv_dev); } diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.h b/drivers/gpu/drm/exynos/exynos_drm_iommu.h index c1584f24d23d..8318ebe2de6d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_iommu.h +++ b/drivers/gpu/drm/exynos/exynos_drm_iommu.h @@ -30,7 +30,7 @@ void drm_iommu_detach_device(struct drm_device *dev_dev, static inline bool is_drm_iommu_supported(struct drm_device *drm_dev) { struct exynos_drm_private *priv = drm_dev->dev_private; - return priv->mapping ? true : false; + return priv->domain ? true : false; } #else