Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp490855imm; Fri, 1 Jun 2018 04:45:39 -0700 (PDT) X-Google-Smtp-Source: ADUXVKKd8S2PCG8n/sKYohfFUo0hjsbI8ucsKdm19bbjJ/nVKq5tdL+AxRdKHsa7q/MqnTC4M3V3 X-Received: by 2002:a63:721c:: with SMTP id n28-v6mr1122059pgc.96.1527853539708; Fri, 01 Jun 2018 04:45:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527853539; cv=none; d=google.com; s=arc-20160816; b=wB5kmsMSFb9UzBndi3XP6LDzJ6bx8Fltq8mDE56SUrQ/jhVmutBbEQey4gV5FoufKd MV0JOLFxyWoqtESdxhyaoZkNEF1YzmQa7f5qc5WfRXPgHrqW/Q3lfvR6gqtkU8Ihq4iV i5odN2+hEcZfIH9oO27CyuD9WcLQNHI0UMdXpIi+40k8mmTNCDR/0AYZegijECCBCrU2 kwOwnqn2wlKzk47Z5G6UCACZ7/6DjQdSn+sIOBpdCL6ubJWNlFsxngjMu84yos0hsCMM kT1bnKoeb6Gw2e/3nHk3IuhfFfHY3Ev/u72ipKOiMx7ruiwrfp3qhxaLOE6gNJFQbsvN U55g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=EZusPZx6trjMF2iPh7Yk+E1iGR5ZiJtB1jXDHsfj4Qg=; b=yKkWyDgpbX7SK8H4MEr2Ye46ZSuO+wnxGgiKAMvPULEL5jzwKU8jM/etDV1KZaIuTv fhhSy3xzSGy4VlLTaVh+KKk80Mj1PGlx/eVSgvmyggMdtRZqTzwI1sQ0HHgDbDG0Jkcw S6I4cHAwe2rWXHqIeB7KoPWtDPvEBqbbgnLdPIHs8rRfcdAAk3+zMC3/KDsqPoVN/a64 L3VDcI1tWM75xKQYOrvzuq+LS29TPu6tL/p1YP/JUAia6iESFanFVp5PBgiOJQRT/sUI Mns9lQETYQQe8CsMAaiRWZrisj0kONQnYumVF3Z1SBKg2kkNNisUqtOO0bh+Z9/iO/rH JRQw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=ck8P9FHp; 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; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g17-v6si38143115plo.355.2018.06.01.04.45.25; Fri, 01 Jun 2018 04:45:39 -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; dkim=pass header.i=@gmail.com header.s=20161025 header.b=ck8P9FHp; 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; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752128AbeFALnW (ORCPT + 99 others); Fri, 1 Jun 2018 07:43:22 -0400 Received: from mail-lf0-f66.google.com ([209.85.215.66]:40159 "EHLO mail-lf0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751889AbeFALls (ORCPT ); Fri, 1 Jun 2018 07:41:48 -0400 Received: by mail-lf0-f66.google.com with SMTP id q11-v6so14383173lfc.7; Fri, 01 Jun 2018 04:41:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=EZusPZx6trjMF2iPh7Yk+E1iGR5ZiJtB1jXDHsfj4Qg=; b=ck8P9FHpxsGO4V6IA6US1JOrU2UU0sGXAIwIcrXqP29AEayG0C9RWfLmIa5e/7e4FM aM6tiogE6/ey90SsqutZyhYI70xbQ+Xh2lSsb/QJnPnEcIC8R756hUc2lccbOedozImh oNpt0pxVqOpypS2QG73EncNJonEm2ds5K7s6DoldxY3ySPMkxj8tp0yE3Bk8nMT32FRx ECovlrW+hL7odxrbo0vJ0oysV5OL2TBBlbDBIu+vfvn7iy/bNar12yBW/S9VrEJbPNzE kZI9oLFlK0ECuojb8hWtn8vC4tb75KxuN0JlNJZTScp39+GgIhQ6EZetwpq6J1Njqe/o XyZg== 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=EZusPZx6trjMF2iPh7Yk+E1iGR5ZiJtB1jXDHsfj4Qg=; b=FaeQ9PloGDe9iSqOsttBudByoClrg+jnpPYzQk5OV8bJEa7FEmoq1s8zitGqv3B+Tl NHr0NgRnxA4NIrr0lFES/aTe4vurCJvb7Kl8NIkxb9gK5x8Hta3muZr3UmT7mqDialUP vqczjxkkS/CVmYnA36LiK8x3DCSp0+QFxD+5w+uccK5q236WbYtRe2NsaQtjr8Jed4qH s7AZfFzWtibsBHkzOtCt5X2Rbj5eUYIAo8CoVrsjBKC1FQYDkKwNx82ADiN4hirbyWzH 1oIFbYXqln3RudoajuKfkvZraFEN9VUT21nsjx9/mrPg9UFUGz448XVtr/XQe+VRyo1E 6BpA== X-Gm-Message-State: ALKqPwctEckTgHGYyERjtIw0414aXt5Xbi1AIz3ADRAFHvZFobaW3nh3 75Iuh1v6Cgp4yogs4pfG2xg= X-Received: by 2002:a19:990f:: with SMTP id b15-v6mr6495542lfe.93.1527853305715; Fri, 01 Jun 2018 04:41:45 -0700 (PDT) Received: from a2k-HP-ProDesk-600-G2-SFF.kyiv.epam.com (ll-51.209.223.85.sovam.net.ua. [85.223.209.51]) by smtp.gmail.com with ESMTPSA id c6-v6sm8066280lja.22.2018.06.01.04.41.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 01 Jun 2018 04:41:44 -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 Cc: daniel.vetter@intel.com, andr2000@gmail.com, dongwon.kim@intel.com, matthew.d.roper@intel.com, Oleksandr Andrushchenko Subject: [PATCH v2 4/9] xen/grant-table: Allow allocating buffers suitable for DMA Date: Fri, 1 Jun 2018 14:41:27 +0300 Message-Id: <20180601114132.22596-5-andr2000@gmail.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180601114132.22596-1-andr2000@gmail.com> References: <20180601114132.22596-1-andr2000@gmail.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 --- drivers/xen/Kconfig | 13 +++++ drivers/xen/grant-table.c | 109 ++++++++++++++++++++++++++++++++++++++ include/xen/grant_table.h | 18 +++++++ 3 files changed, 140 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..5658e58d9cc6 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 @@ -811,6 +815,73 @@ int gnttab_alloc_pages(int nr_pages, struct page **pages) } EXPORT_SYMBOL_GPL(gnttab_alloc_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_err("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_err("Failed to decrease reservation for DMA buffer\n"); + ret = -EFAULT; + goto fail_free_dma; + } + + ret = gnttab_pages_set_private(args->nr_pages, args->pages); + if (ret < 0) + goto fail_clear_private; + + return 0; + +fail_clear_private: + gnttab_pages_clear_private(args->nr_pages, args->pages); +fail_free_dma: + xenmem_reservation_increase(args->nr_pages, args->frames); + xenmem_reservation_va_mapping_update(args->nr_pages, args->pages, + args->frames); + 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_alloc_pages); +#endif + void gnttab_pages_clear_private(int nr_pages, struct page **pages) { int i; @@ -838,6 +909,44 @@ void gnttab_free_pages(int nr_pages, struct page **pages) } EXPORT_SYMBOL_GPL(gnttab_free_pages); +#ifdef CONFIG_XEN_GRANT_DMA_ALLOC +/** + * 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_err("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); -- 2.17.0