From patchwork Mon Aug 7 12:22:51 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksandr Andrushchenko X-Patchwork-Id: 9885233 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 4540960363 for ; Mon, 7 Aug 2017 12:25:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3687F28670 for ; Mon, 7 Aug 2017 12:25:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2B90328676; Mon, 7 Aug 2017 12:25:01 +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=-1.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=no version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 50E9528670 for ; Mon, 7 Aug 2017 12:25:00 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id DF5E9267287; Mon, 7 Aug 2017 14:23:21 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 4B221267267; Mon, 7 Aug 2017 14:23:18 +0200 (CEST) Received: from mail-lf0-f68.google.com (mail-lf0-f68.google.com [209.85.215.68]) by alsa0.perex.cz (Postfix) with ESMTP id 1DB79267235 for ; Mon, 7 Aug 2017 14:23:10 +0200 (CEST) Received: by mail-lf0-f68.google.com with SMTP id 65so225319lfa.0 for ; Mon, 07 Aug 2017 05:23:10 -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=LFYwnwpcnAtHMaD8S6xEeS5DWFjFyt95VLMDVObaWp0=; b=E+ttvjl9J1axEOTJDphm8zFuI1aPN/omWVQR9WMf6GWCAN6+7wf8xcrftOPRBh1hbZ EDHTc9xC9Old+5Ofdw1OswHvZk0BDahTNOeg119RCLLVErKFXN5hmroI/hc3F4+fmnta V4tuL0+OIZnjHawfY+GXtjzoIzILxjGaAXXLm3B3Uh1qABL67/d0/zC8io2tkxLf3DTz BJMpWAY7aO1bU+FzHd5hVTjJ5EvJgE0QXOT0RAQ1axO/zwVNJWh9HsHXuZnp1Ncr+w8i 6k61yDFQM0C7jCQktehaFUphdLKLuN8MT0JB/0X6TjbF4OvdcX3sM57BtD351niltuPN 5Suw== 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=LFYwnwpcnAtHMaD8S6xEeS5DWFjFyt95VLMDVObaWp0=; b=HSLjvJsLFXLgLdpLiJ617C56GojI1PuH7LAvf8zu6+xIMDNlXgp5GwIZUUKhk1c2k2 9x8Ic7RRD9ZsVce07ymOnx1+y/vKNUN01vHMyJiwQSeC8Sm4Hm639duDY30trYt2OVnp oG/CzmpyX64e13AkR3WaWSwwxIgpCkD6wCYyFOcRyi+XpdyWNRUGFgqRXqVgM95fTaE2 P9+e3jOh4dTTqMs/YCseB7NzdYNaKlOJoTOpnmUL8M9FB5S2+n0/W5BE5wg5vvtpYhKS bVbXMZCzchoMCWtZUF21jGrJEFaJHjOo0x1rT2T65pHQFvUejRppsqUquw2U4z6g7dOb ld7A== X-Gm-Message-State: AHYfb5hiLW4spkdvB6032reSz1HnywzC2Sg04d1t5Hr2cvXmRhUuygxj zSca1diJYPqQBlV+ X-Received: by 10.46.33.151 with SMTP id h23mr130877lji.66.1502108590204; Mon, 07 Aug 2017 05:23:10 -0700 (PDT) Received: from a2k-HP-ProDesk-600-G2-SFF.kyiv.epam.com (ll-53.209.223.85.sovam.net.ua. [85.223.209.53]) by smtp.gmail.com with ESMTPSA id m143sm1031821lfm.77.2017.08.07.05.23.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 07 Aug 2017 05:23:09 -0700 (PDT) From: Oleksandr Andrushchenko To: alsa-devel@alsa-project.org, xen-devel@lists.xen.org, linux-kernel@vger.kernel.org Date: Mon, 7 Aug 2017 15:22:51 +0300 Message-Id: <1502108577-8099-7-git-send-email-andr2000@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1502108577-8099-1-git-send-email-andr2000@gmail.com> References: <1502108577-8099-1-git-send-email-andr2000@gmail.com> Cc: andr2000@gmail.com, Oleksandr Andrushchenko , tiwai@suse.com Subject: [alsa-devel] [PATCH RESEND1 06/12] ALSA: vsnd: Implement handling of shared buffers X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP From: Oleksandr Andrushchenko Implement shared buffer handling according to the para-virtualized sound device protocol at xen/interface/io/sndif.h: - manage buffer memory - handle granted references - handle page directories Signed-off-by: Oleksandr Andrushchenko --- sound/drivers/xen-front.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) diff --git a/sound/drivers/xen-front.c b/sound/drivers/xen-front.c index a92459b2737e..04ebc15757f4 100644 --- a/sound/drivers/xen-front.c +++ b/sound/drivers/xen-front.c @@ -58,6 +58,14 @@ struct xdrv_evtchnl_info { uint16_t resp_id; }; +struct sh_buf_info { + int num_grefs; + grant_ref_t *grefs; + uint8_t *vdirectory; + uint8_t *vbuffer; + size_t vbuffer_sz; +}; + struct cfg_stream { int unique_id; char *xenstore_path; @@ -825,6 +833,176 @@ static void xdrv_remove_internal(struct xdrv_info *drv_info) xdrv_evtchnl_free_all(drv_info); } +static inline grant_ref_t sh_buf_get_dir_start(struct sh_buf_info *buf) +{ + if (!buf->grefs) + return GRANT_INVALID_REF; + return buf->grefs[0]; +} + +static inline void sh_buf_clear(struct sh_buf_info *buf) +{ + memset(buf, 0, sizeof(*buf)); +} + +static void sh_buf_free(struct sh_buf_info *buf) +{ + int i; + + if (buf->grefs) { + for (i = 0; i < buf->num_grefs; i++) + if (buf->grefs[i] != GRANT_INVALID_REF) + gnttab_end_foreign_access(buf->grefs[i], + 0, 0UL); + kfree(buf->grefs); + } + kfree(buf->vdirectory); + free_pages_exact(buf->vbuffer, buf->vbuffer_sz); + sh_buf_clear(buf); +} + +/* + * number of grant references a page can hold with respect to the + * xendispl_page_directory header + */ +#define XENSND_NUM_GREFS_PER_PAGE ((XEN_PAGE_SIZE - \ + offsetof(struct xensnd_page_directory, gref)) / \ + sizeof(grant_ref_t)) + +static void sh_buf_fill_page_dir(struct sh_buf_info *buf, int num_pages_dir) +{ + struct xensnd_page_directory *page_dir; + unsigned char *ptr; + int i, cur_gref, grefs_left, to_copy; + + ptr = buf->vdirectory; + grefs_left = buf->num_grefs - num_pages_dir; + /* + * skip grant references at the beginning, they are for pages granted + * for the page directory itself + */ + cur_gref = num_pages_dir; + for (i = 0; i < num_pages_dir; i++) { + page_dir = (struct xensnd_page_directory *)ptr; + if (grefs_left <= XENSND_NUM_GREFS_PER_PAGE) { + to_copy = grefs_left; + page_dir->gref_dir_next_page = GRANT_INVALID_REF; + } else { + to_copy = XENSND_NUM_GREFS_PER_PAGE; + page_dir->gref_dir_next_page = buf->grefs[i + 1]; + } + memcpy(&page_dir->gref, &buf->grefs[cur_gref], + to_copy * sizeof(grant_ref_t)); + ptr += XEN_PAGE_SIZE; + grefs_left -= to_copy; + cur_gref += to_copy; + } +} + +static int sh_buf_grant_refs(struct xenbus_device *xb_dev, + struct sh_buf_info *buf, + int num_pages_dir, int num_pages_vbuffer, int num_grefs) +{ + grant_ref_t priv_gref_head; + int ret, i, j, cur_ref; + int otherend_id; + + ret = gnttab_alloc_grant_references(num_grefs, &priv_gref_head); + if (ret) + return ret; + + buf->num_grefs = num_grefs; + otherend_id = xb_dev->otherend_id; + j = 0; + + for (i = 0; i < num_pages_dir; i++) { + cur_ref = gnttab_claim_grant_reference(&priv_gref_head); + if (cur_ref < 0) { + ret = cur_ref; + goto fail; + } + + gnttab_grant_foreign_access_ref(cur_ref, otherend_id, + xen_page_to_gfn(virt_to_page(buf->vdirectory + + XEN_PAGE_SIZE * i)), 0); + buf->grefs[j++] = cur_ref; + } + + for (i = 0; i < num_pages_vbuffer; i++) { + cur_ref = gnttab_claim_grant_reference(&priv_gref_head); + if (cur_ref < 0) { + ret = cur_ref; + goto fail; + } + + gnttab_grant_foreign_access_ref(cur_ref, otherend_id, + xen_page_to_gfn(virt_to_page(buf->vbuffer + + XEN_PAGE_SIZE * i)), 0); + buf->grefs[j++] = cur_ref; + } + + gnttab_free_grant_references(priv_gref_head); + sh_buf_fill_page_dir(buf, num_pages_dir); + return 0; + +fail: + gnttab_free_grant_references(priv_gref_head); + return ret; +} + +static int sh_buf_alloc_int_buffers(struct sh_buf_info *buf, + int num_pages_dir, int num_pages_vbuffer, int num_grefs) +{ + buf->grefs = kcalloc(num_grefs, sizeof(*buf->grefs), GFP_KERNEL); + if (!buf->grefs) + return -ENOMEM; + + buf->vdirectory = kcalloc(num_pages_dir, XEN_PAGE_SIZE, GFP_KERNEL); + if (!buf->vdirectory) + goto fail; + + buf->vbuffer_sz = num_pages_vbuffer * XEN_PAGE_SIZE; + buf->vbuffer = alloc_pages_exact(buf->vbuffer_sz, GFP_KERNEL); + if (!buf->vbuffer) + goto fail; + return 0; + +fail: + kfree(buf->grefs); + buf->grefs = NULL; + kfree(buf->vdirectory); + buf->vdirectory = NULL; + return -ENOMEM; +} + +static int sh_buf_alloc(struct xenbus_device *xb_dev, + struct sh_buf_info *buf, unsigned int buffer_size) +{ + int num_pages_vbuffer, num_pages_dir, num_grefs; + int ret; + + sh_buf_clear(buf); + + num_pages_vbuffer = DIV_ROUND_UP(buffer_size, XEN_PAGE_SIZE); + /* number of pages the page directory consumes itself */ + num_pages_dir = DIV_ROUND_UP(num_pages_vbuffer, + XENSND_NUM_GREFS_PER_PAGE); + num_grefs = num_pages_vbuffer + num_pages_dir; + + ret = sh_buf_alloc_int_buffers(buf, num_pages_dir, + num_pages_vbuffer, num_grefs); + if (ret < 0) + return ret; + + ret = sh_buf_grant_refs(xb_dev, buf, + num_pages_dir, num_pages_vbuffer, num_grefs); + if (ret < 0) + return ret; + + sh_buf_fill_page_dir(buf, num_pages_dir); + return 0; +} + static int xdrv_be_on_initwait(struct xdrv_info *drv_info) { int stream_idx;