From patchwork Tue Jun 12 13:41:55 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksandr Andrushchenko X-Patchwork-Id: 10460327 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 C5355602A0 for ; Tue, 12 Jun 2018 13:42:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A567528773 for ; Tue, 12 Jun 2018 13:42:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9A359287A8; Tue, 12 Jun 2018 13:42:21 +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_ADSP_CUSTOM_MED, FREEMAIL_FROM, MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 27FA328773 for ; Tue, 12 Jun 2018 13:42:21 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 2DB876E4D7; Tue, 12 Jun 2018 13:42:19 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-lf0-x244.google.com (mail-lf0-x244.google.com [IPv6:2a00:1450:4010:c07::244]) by gabe.freedesktop.org (Postfix) with ESMTPS id E38606E4D3 for ; Tue, 12 Jun 2018 13:42:16 +0000 (UTC) Received: by mail-lf0-x244.google.com with SMTP id y20-v6so36138030lfy.0 for ; Tue, 12 Jun 2018 06:42:16 -0700 (PDT) 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:in-reply-to :references; bh=7b9yXN8I7+y9xFpsRLeuFAzs6185E05kVswKBKHWIhk=; b=F5rXvg87vqOD8AoATMCwzgTc1YeRKZxxaPWarfibL0ccbxwCijo2+kpywXjSR5//Oh DjAxZfvINgG2/DcW1aDKerH3zpqLT6Dyc1aWRE+MiXJzQlXC8bCeY86hT2otjqgLbvkl +m/MAgY8hMOMcyXe7OlVVTAInfHOwIXcYpUx9dWgBdUGJSVVSkaxohCqz93Bkj/A7Zlq G6lgJCSSYyW53aeNYm4jZM3/vmcRVUSPA4zT2hG2GAzheGPQYpRMt12kMJpUqOxmU3Sc GSPg2WS0NaTxLIPVAdadEYX3YZD6ai2QjuNT1gzioTSzUrPEvWSjrQAhYfQANzwyVBbM iZGA== X-Gm-Message-State: APt69E0hvnH4vJxp3Ny1ICadXrGa8lEHq1Sn8SWpD5HdL5lFvgOKwdDX VlyprcZnBQJrErXhw3ku95I= X-Google-Smtp-Source: ADUXVKLVIinkAgOji5KlhLRpd4xPEUBeGTsZKGWxcRFNG7iBHah0vwdWuTk0Tt+X6TOsEDo9ARLI+Q== X-Received: by 2002:a2e:8810:: with SMTP id x16-v6mr296535ljh.45.1528810935279; Tue, 12 Jun 2018 06:42:15 -0700 (PDT) Received: from a2k-HP-ProDesk-600-G2-SFF.kyiv.epam.com (ll-74.141.223.85.sovam.net.ua. [85.223.141.74]) by smtp.gmail.com with ESMTPSA id x18-v6sm46692ljh.63.2018.06.12.06.42.13 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 12 Jun 2018 06:42:14 -0700 (PDT) From: Oleksandr Andrushchenko To: xen-devel@lists.xenproject.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-media@vger.kernel.org, jgross@suse.com, boris.ostrovsky@oracle.com, konrad.wilk@oracle.com Subject: [PATCH v3 4/9] xen/grant-table: Allow allocating buffers suitable for DMA Date: Tue, 12 Jun 2018 16:41:55 +0300 Message-Id: <20180612134200.17456-5-andr2000@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180612134200.17456-1-andr2000@gmail.com> References: <20180612134200.17456-1-andr2000@gmail.com> X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: andr2000@gmail.com, daniel.vetter@intel.com, dongwon.kim@intel.com, Oleksandr Andrushchenko MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Oleksandr Andrushchenko Extend grant table module API to allow allocating buffers that can be used for DMA operations and mapping foreign grant references on top of those. The resulting buffer is similar to the one allocated by the balloon driver in terms that proper memory reservation is made ({increase|decrease}_reservation and VA mappings updated if needed). This is useful for sharing foreign buffers with HW drivers which cannot work with scattered buffers provided by the balloon driver, but require DMAable memory instead. Signed-off-by: Oleksandr Andrushchenko Reviewed-by: Boris Ostrovsky --- drivers/xen/Kconfig | 13 ++++++ drivers/xen/grant-table.c | 97 +++++++++++++++++++++++++++++++++++++++ include/xen/grant_table.h | 18 ++++++++ 3 files changed, 128 insertions(+) diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index e5d0c28372ea..39536ddfbce4 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig @@ -161,6 +161,19 @@ config XEN_GRANT_DEV_ALLOC to other domains. This can be used to implement frontend drivers or as part of an inter-domain shared memory channel. +config XEN_GRANT_DMA_ALLOC + bool "Allow allocating DMA capable buffers with grant reference module" + depends on XEN && HAS_DMA + help + Extends grant table module API to allow allocating DMA capable + buffers and mapping foreign grant references on top of it. + The resulting buffer is similar to one allocated by the balloon + driver in terms that proper memory reservation is made + ({increase|decrease}_reservation and VA mappings updated if needed). + This is useful for sharing foreign buffers with HW drivers which + cannot work with scattered buffers provided by the balloon driver, + but require DMAable memory instead. + config SWIOTLB_XEN def_bool y select SWIOTLB diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index dbb48a89e987..26ed498b5e6d 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -45,6 +45,9 @@ #include #include #include +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC +#include +#endif #include #include @@ -57,6 +60,7 @@ #ifdef CONFIG_X86 #include #endif +#include #include #include @@ -838,6 +842,99 @@ void gnttab_free_pages(int nr_pages, struct page **pages) } EXPORT_SYMBOL_GPL(gnttab_free_pages); +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC +/** + * gnttab_dma_alloc_pages - alloc DMAable pages suitable for grant mapping into + * @args: arguments to the function + */ +int gnttab_dma_alloc_pages(struct gnttab_dma_alloc_args *args) +{ + unsigned long pfn, start_pfn; + size_t size; + int i, ret; + + size = args->nr_pages << PAGE_SHIFT; + if (args->coherent) + args->vaddr = dma_alloc_coherent(args->dev, size, + &args->dev_bus_addr, + GFP_KERNEL | __GFP_NOWARN); + else + args->vaddr = dma_alloc_wc(args->dev, size, + &args->dev_bus_addr, + GFP_KERNEL | __GFP_NOWARN); + if (!args->vaddr) { + pr_debug("Failed to allocate DMA buffer of size %zu\n", size); + return -ENOMEM; + } + + start_pfn = __phys_to_pfn(args->dev_bus_addr); + for (pfn = start_pfn, i = 0; pfn < start_pfn + args->nr_pages; + pfn++, i++) { + struct page *page = pfn_to_page(pfn); + + args->pages[i] = page; + args->frames[i] = xen_page_to_gfn(page); + xenmem_reservation_scrub_page(page); + } + + xenmem_reservation_va_mapping_reset(args->nr_pages, args->pages); + + ret = xenmem_reservation_decrease(args->nr_pages, args->frames); + if (ret != args->nr_pages) { + pr_debug("Failed to decrease reservation for DMA buffer\n"); + ret = -EFAULT; + goto fail; + } + + ret = gnttab_pages_set_private(args->nr_pages, args->pages); + if (ret < 0) + goto fail; + + return 0; + +fail: + gnttab_dma_free_pages(args); + return ret; +} +EXPORT_SYMBOL_GPL(gnttab_dma_alloc_pages); + +/** + * gnttab_dma_free_pages - free DMAable pages + * @args: arguments to the function + */ +int gnttab_dma_free_pages(struct gnttab_dma_alloc_args *args) +{ + size_t size; + int i, ret; + + gnttab_pages_clear_private(args->nr_pages, args->pages); + + for (i = 0; i < args->nr_pages; i++) + args->frames[i] = page_to_xen_pfn(args->pages[i]); + + ret = xenmem_reservation_increase(args->nr_pages, args->frames); + if (ret != args->nr_pages) { + pr_debug("Failed to decrease reservation for DMA buffer\n"); + ret = -EFAULT; + } else { + ret = 0; + } + + xenmem_reservation_va_mapping_update(args->nr_pages, args->pages, + args->frames); + + size = args->nr_pages << PAGE_SHIFT; + if (args->coherent) + dma_free_coherent(args->dev, size, + args->vaddr, args->dev_bus_addr); + else + dma_free_wc(args->dev, size, + args->vaddr, args->dev_bus_addr); + return ret; +} +EXPORT_SYMBOL_GPL(gnttab_dma_free_pages); +#endif + /* Handling of paged out grant targets (GNTST_eagain) */ #define MAX_DELAY 256 static inline void diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h index de03f2542bb7..9bc5bc07d4d3 100644 --- a/include/xen/grant_table.h +++ b/include/xen/grant_table.h @@ -198,6 +198,24 @@ void gnttab_free_auto_xlat_frames(void); int gnttab_alloc_pages(int nr_pages, struct page **pages); void gnttab_free_pages(int nr_pages, struct page **pages); +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC +struct gnttab_dma_alloc_args { + /* Device for which DMA memory will be/was allocated. */ + struct device *dev; + /* If set then DMA buffer is coherent and write-combine otherwise. */ + bool coherent; + + int nr_pages; + struct page **pages; + xen_pfn_t *frames; + void *vaddr; + dma_addr_t dev_bus_addr; +}; + +int gnttab_dma_alloc_pages(struct gnttab_dma_alloc_args *args); +int gnttab_dma_free_pages(struct gnttab_dma_alloc_args *args); +#endif + int gnttab_pages_set_private(int nr_pages, struct page **pages); void gnttab_pages_clear_private(int nr_pages, struct page **pages);