From patchwork Mon Aug 7 07:43:10 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleksandr Andrushchenko X-Patchwork-Id: 9884845 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 2B9DC60363 for ; Mon, 7 Aug 2017 09:28:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1F5D8285D1 for ; Mon, 7 Aug 2017 09:28:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 141252860A; Mon, 7 Aug 2017 09:28:44 +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 3D099285D1 for ; Mon, 7 Aug 2017 09:28:43 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 307F226706B; Mon, 7 Aug 2017 11:26:57 +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 45D96267048; Mon, 7 Aug 2017 09:43:44 +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 9B3AA26703C for ; Mon, 7 Aug 2017 09:43:40 +0200 (CEST) Received: by mail-lf0-f68.google.com with SMTP id 65so4871893lfa.0 for ; Mon, 07 Aug 2017 00:43:40 -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=fQaSDJyz2ex561VWBqGoSYcobDipbNNCa5yEDT38ZNhmr9ucWKkMGEyRqeJblSNHIV V23eBYlIVbKwFPG/NO1D42Os9w9lfRyMnZ9iJu102lt8kb58Mcg7+Ybnnf6284IUdqjy x5Ius0DzKUKbRs4ryuIG7PG+IhfXR1TJ8QaQAvjMYqid+I9jIT6LFwnfwql/+XRH4gwK qQcHvemXZirEPiv9dn19zSULtos894kf5f63s1p9uOT0TE2oXMVvtzgYQeC0SGxZiR6D hLYm3Ch9NAZ0brLJWTEsVwnGCTiqp4KvWbaymG5Zwc7tx9R5mTcLfKpW4EkiDEBgELMv xPww== 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=TXZRlgZyb9B19jcQUouEY1gybjkFqhdWsS0wZ9v97ETDe2HMUz7jrF9s/LKjNCLpI0 Muy4wIeAZJR1WvBnWzE+L39oZmQGc4eAlqHUv8oo17ILoInZAyrGteVLDLOMmynsuJNp 5BR39PYiZpPO+1gMpaZ0yg+PQ2oWaw2VF0yDm0Won1hEPKlOLQbrY1/jHVYtMbHFb+hz R/r4+/7IqTD1gEIGNLI6BbbZ3t3CtEwvCLAAUVgYhLsljayppEnhlVmBYGE5e0SOLib0 Mwez9oHnvscaRenOm0xa+znAeuC0dFMWQLXdtzXnGgdju353mzeDlFGmrFCONsJIw8jM XPVw== X-Gm-Message-State: AIVw113hP/s32ysqwv17ZrJWBzdGaPaXI9LhnaqeDlFMHwlzkMQ0iLJT 2QPzB6/GOevfFYV4 X-Received: by 10.46.88.14 with SMTP id m14mr3677366ljb.33.1502091819963; Mon, 07 Aug 2017 00:43:39 -0700 (PDT) Received: from a2k-HP-ProDesk-600-G2-SFF.kyiv.epam.com (ll-52.209.223.85.sovam.net.ua. [85.223.209.52]) by smtp.gmail.com with ESMTPSA id f136sm399062lff.34.2017.08.07.00.43.38 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 07 Aug 2017 00:43:39 -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 10:43:10 +0300 Message-Id: <1502091796-14413-6-git-send-email-andr2000@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1502091796-14413-1-git-send-email-andr2000@gmail.com> References: <1502091796-14413-1-git-send-email-andr2000@gmail.com> X-Mailman-Approved-At: Mon, 07 Aug 2017 11:26:50 +0200 Cc: andr2000@gmail.com, Oleksandr Andrushchenko , tiwai@suse.com Subject: [alsa-devel] [PATCH 05/11] 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;