Received: by 10.192.165.156 with SMTP id m28csp1713443imm; Tue, 17 Apr 2018 04:22:47 -0700 (PDT) X-Google-Smtp-Source: AIpwx4/ThKW4CovFXGbY0B5kYSR1eVDg7OGxVhgsBnMczBh7PUrPPV+CEGqxPaQxv3/DaW6uL1IO X-Received: by 10.99.117.93 with SMTP id f29mr1382041pgn.401.1523964167023; Tue, 17 Apr 2018 04:22:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1523964166; cv=none; d=google.com; s=arc-20160816; b=BAnbxZ0Q6m7vpROJfaa3xwyPA9YHP43s2x+hrfDbmnf7VxC4f3VPsLeUlgtzmj9VRJ A3Z5si5Ng6q259/ol1HJNvVZPA3ZazDLW13lJq0kknEvZfJd4Qdz5vEqnnNfCRn0irrb vPRE5JLMep3VIif8zAdaQSY00z51BqsPJa2LycRpGZOKijZbObMgvz/JHvvLb5cACh9B vKpTKrj5ZnZ0e5H25huujZVXltT90JTLbAYUfnsoE6QGDhln6jjOT8Ww02RjrWOlUEFD dhuQSoPD5N88elNvZUw/43DXE9WWU1KK6TZ31t+s7D6/rU/5GWcbpbwAknr5z85Hu62Z gN3w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-language :content-transfer-encoding:in-reply-to:mime-version:user-agent:date :message-id:from:references:cc:to:subject:dkim-signature :arc-authentication-results; bh=skfv8IFb6Vdl1Q8pI4PDAL7lkZKWZ508mkB0YWLXL7U=; b=tu564lx9mO2zuKxeOk7rmhh3JIo+1qCIpWOMC1ipGpZKcXXXs40T2Ly/Ea0iVSGV6M 7T8U6Lm0V8TQ7fIEAx+s4BzEZOaccoBqFgGSlm7szHWAJJiVyV403jcE3zKLlXDtN3Qw O0ZaASziTuDt0l/6pulFFLx9HDSxkwvsZ5h4Wo6WLETPQxM/JsXboTMY1wKGokn7lYgT uTr3XOd2NJQQQBgIR0dzDuhFyYdbs0L8Jgp07f7gc4VxNXk0ElZG3chRSU5bZS8FQfl7 6A33FRaFFLsLJs/Yrv7nhiX2k375KYTRyc5p5+UIW44gs5289ktFSNcIGyIoN1h54VXO 6Udw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=DvVFc6NW; 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 b12si1214549pge.252.2018.04.17.04.22.32; Tue, 17 Apr 2018 04:22:46 -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=DvVFc6NW; 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 S1752795AbeDQLVL (ORCPT + 99 others); Tue, 17 Apr 2018 07:21:11 -0400 Received: from mail-lf0-f66.google.com ([209.85.215.66]:36068 "EHLO mail-lf0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752116AbeDQLVK (ORCPT ); Tue, 17 Apr 2018 07:21:10 -0400 Received: by mail-lf0-f66.google.com with SMTP id d20-v6so26745007lfe.3 for ; Tue, 17 Apr 2018 04:21:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=subject:to:cc:references:from:message-id:date:user-agent :mime-version:in-reply-to:content-transfer-encoding:content-language; bh=skfv8IFb6Vdl1Q8pI4PDAL7lkZKWZ508mkB0YWLXL7U=; b=DvVFc6NWfDJrjldyn1/DFFaZyBlUAVJFDWaIAPWLo4bJyMlg7YdT4GChOjbrBycb5V wBuVGeKAN4ralc2IdHm+GubQ/1DSFAnD1tQWDPL/0ps3Qe2/R54XAmVMrr6LduxwZDYl KYaVIViV+iSeKsk+aASxBMMz9k22Kql8/zmx9pGEDhhXvZHIuJmLJOtDgxWcNybQeJJW 8jIafKjmrJKTZKmwIMEpif78mDxjcRfP8q1zPOxv+CnEP7t7d0dFOhkQnO5b0bwjlZCA zA0WMXO++i5jSOtYDX7MWO42mE72vdInOgIiKqaRaumswA2/H8P8x1cLpPaKGPkCzVrc FGUw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-transfer-encoding :content-language; bh=skfv8IFb6Vdl1Q8pI4PDAL7lkZKWZ508mkB0YWLXL7U=; b=OuJyADab7H8JK9qfbWWgeeWl1llyp3b9cdol5z3hsyXKM/aYRMYUVdgZf/pI0haKPQ /YCXXsoCMte7TjAXqWSHYf/87ETk7QcyLNuIaunK7LKlVi56xAdIwG3TmUIjv3shBJ+t xxPOwlDJdNilgVb0mKvAjk1on9lczDNwHrWAxM5CTAXtLOu4IcfOvPfU/vHbwsR1izf9 vrGAeMC1eeDyY5y8Kd20osgEzSe9puiQchRnIbTt92g37nuceukbJJ/5iBOa4ITnaYJR DCHT7xzbNBx57avonpa15IEkYxhOx29Ak52B831G/b0ov7qvLDhpNQ103vUedInOAIC4 hIrQ== X-Gm-Message-State: ALQs6tDWJyKdMnCHQaOtLeGil0fynpZ3lUZM1LCypVGqGQim1y9IEtwz IQDEdirSwll0QhHgsTQOfAo= X-Received: by 10.46.128.90 with SMTP id p26mr1289901ljg.141.1523964068238; Tue, 17 Apr 2018 04:21:08 -0700 (PDT) Received: from [10.17.182.9] (ll-74.141.223.85.sovam.net.ua. [85.223.141.74]) by smtp.gmail.com with ESMTPSA id d4-v6sm3350118lfg.65.2018.04.17.04.21.06 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Apr 2018 04:21:07 -0700 (PDT) Subject: Re: [PATCH v2 3/5] ALSA: xen-front: Implement Xen event channel handling To: Juergen Gross , xen-devel@lists.xenproject.org, linux-kernel@vger.kernel.org, alsa-devel@alsa-project.org, boris.ostrovsky@oracle.com, konrad.wilk@oracle.com, perex@perex.cz, tiwai@suse.com Cc: Oleksandr Andrushchenko References: <20180416062453.24743-1-andr2000@gmail.com> <20180416062453.24743-4-andr2000@gmail.com> <2e06f714-ebc2-11bb-078b-8a453ea8464c@gmail.com> From: Oleksandr Andrushchenko Message-ID: Date: Tue, 17 Apr 2018 14:21:06 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.7.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-US Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 04/17/2018 02:14 PM, Juergen Gross wrote: > On 17/04/18 10:58, Oleksandr Andrushchenko wrote: >> On 04/16/2018 04:12 PM, Juergen Gross wrote: >>> On 16/04/18 08:24, Oleksandr Andrushchenko wrote: >>>> From: Oleksandr Andrushchenko >>>> >>>> Handle Xen event channels: >>>>    - create for all configured streams and publish >>>>      corresponding ring references and event channels in Xen store, >>>>      so backend can connect >>>>    - implement event channels interrupt handlers >>>>    - create and destroy event channels with respect to Xen bus state >>>> >>>> Signed-off-by: Oleksandr Andrushchenko >>>> >>>> --- >>>>   sound/xen/Makefile                |   3 +- >>>>   sound/xen/xen_snd_front.c         |  10 +- >>>>   sound/xen/xen_snd_front.h         |   7 + >>>>   sound/xen/xen_snd_front_evtchnl.c | 474 >>>> ++++++++++++++++++++++++++++++++++++++ >>>>   sound/xen/xen_snd_front_evtchnl.h |  92 ++++++++ >>>>   5 files changed, 584 insertions(+), 2 deletions(-) >>>>   create mode 100644 sound/xen/xen_snd_front_evtchnl.c >>>>   create mode 100644 sound/xen/xen_snd_front_evtchnl.h >>>> >>>> diff --git a/sound/xen/Makefile b/sound/xen/Makefile >>>> index 06705bef61fa..03c669984000 100644 >>>> --- a/sound/xen/Makefile >>>> +++ b/sound/xen/Makefile >>>> @@ -1,6 +1,7 @@ >>>>   # SPDX-License-Identifier: GPL-2.0 OR MIT >>>>     snd_xen_front-objs := xen_snd_front.o \ >>>> -              xen_snd_front_cfg.o >>>> +              xen_snd_front_cfg.o \ >>>> +              xen_snd_front_evtchnl.o >>>>     obj-$(CONFIG_SND_XEN_FRONTEND) += snd_xen_front.o >>>> diff --git a/sound/xen/xen_snd_front.c b/sound/xen/xen_snd_front.c >>>> index 65d2494a9d14..eb46bf4070f9 100644 >>>> --- a/sound/xen/xen_snd_front.c >>>> +++ b/sound/xen/xen_snd_front.c >>>> @@ -18,9 +18,11 @@ >>>>   #include >>>>     #include "xen_snd_front.h" >>>> +#include "xen_snd_front_evtchnl.h" >>> Does it really make sense to have multiple driver-private headers? >>> >>> I think those can be merged. >> I would really like to keep it separate as it clearly >> shows which stuff belongs to which modules. >> At least for me it is easier to maintain it this way. >>>>     static void xen_snd_drv_fini(struct xen_snd_front_info *front_info) >>>>   { >>>> +    xen_snd_front_evtchnl_free_all(front_info); >>>>   } >>>>     static int sndback_initwait(struct xen_snd_front_info *front_info) >>>> @@ -32,7 +34,12 @@ static int sndback_initwait(struct >>>> xen_snd_front_info *front_info) >>>>       if (ret < 0) >>>>           return ret; >>>>   -    return 0; >>>> +    /* create event channels for all streams and publish */ >>>> +    ret = xen_snd_front_evtchnl_create_all(front_info, num_streams); >>>> +    if (ret < 0) >>>> +        return ret; >>>> + >>>> +    return xen_snd_front_evtchnl_publish_all(front_info); >>>>   } >>>>     static int sndback_connect(struct xen_snd_front_info *front_info) >>>> @@ -122,6 +129,7 @@ static int xen_drv_probe(struct xenbus_device >>>> *xb_dev, >>>>           return -ENOMEM; >>>>         front_info->xb_dev = xb_dev; >>>> +    spin_lock_init(&front_info->io_lock); >>>>       dev_set_drvdata(&xb_dev->dev, front_info); >>>>         return xenbus_switch_state(xb_dev, XenbusStateInitialising); >>>> diff --git a/sound/xen/xen_snd_front.h b/sound/xen/xen_snd_front.h >>>> index b52226cb30bc..9c2ffbb4e4b8 100644 >>>> --- a/sound/xen/xen_snd_front.h >>>> +++ b/sound/xen/xen_snd_front.h >>>> @@ -13,9 +13,16 @@ >>>>     #include "xen_snd_front_cfg.h" >>>>   +struct xen_snd_front_evtchnl_pair; >>>> + >>>>   struct xen_snd_front_info { >>>>       struct xenbus_device *xb_dev; >>>>   +    /* serializer for backend IO: request/response */ >>>> +    spinlock_t io_lock; >>>> +    int num_evt_pairs; >>>> +    struct xen_snd_front_evtchnl_pair *evt_pairs; >>>> + >>>>       struct xen_front_cfg_card cfg; >>>>   }; >>>>   diff --git a/sound/xen/xen_snd_front_evtchnl.c >>>> b/sound/xen/xen_snd_front_evtchnl.c >>>> new file mode 100644 >>>> index 000000000000..9ece39f938f8 >>>> --- /dev/null >>>> +++ b/sound/xen/xen_snd_front_evtchnl.c >>>> @@ -0,0 +1,474 @@ >>>> +// SPDX-License-Identifier: GPL-2.0 OR MIT >>>> + >>>> +/* >>>> + * Xen para-virtual sound device >>>> + * >>>> + * Copyright (C) 2016-2018 EPAM Systems Inc. >>>> + * >>>> + * Author: Oleksandr Andrushchenko >>>> + */ >>>> + >>>> +#include >>>> +#include >>>> +#include >>>> +#include >>>> + >>>> +#include "xen_snd_front.h" >>>> +#include "xen_snd_front_cfg.h" >>>> +#include "xen_snd_front_evtchnl.h" >>>> + >>>> +static irqreturn_t evtchnl_interrupt_req(int irq, void *dev_id) >>>> +{ >>>> +    struct xen_snd_front_evtchnl *channel = dev_id; >>>> +    struct xen_snd_front_info *front_info = channel->front_info; >>>> +    struct xensnd_resp *resp; >>>> +    RING_IDX i, rp; >>>> +    unsigned long flags; >>>> + >>>> +    if (unlikely(channel->state != EVTCHNL_STATE_CONNECTED)) >>>> +        return IRQ_HANDLED; >>>> + >>>> +    spin_lock_irqsave(&front_info->io_lock, flags); >>>> + >>>> +again: >>>> +    rp = channel->u.req.ring.sring->rsp_prod; >>>> +    /* ensure we see queued responses up to rp */ >>>> +    rmb(); >>>> + >>>> +    for (i = channel->u.req.ring.rsp_cons; i != rp; i++) { >>>> +        resp = RING_GET_RESPONSE(&channel->u.req.ring, i); >>>> +        if (resp->id != channel->evt_id) >>>> +            continue; >>>> +        switch (resp->operation) { >>>> +        case XENSND_OP_OPEN: >>>> +            /* fall through */ >>>> +        case XENSND_OP_CLOSE: >>>> +            /* fall through */ >>>> +        case XENSND_OP_READ: >>>> +            /* fall through */ >>>> +        case XENSND_OP_WRITE: >>>> +            /* fall through */ >>>> +        case XENSND_OP_TRIGGER: >>>> +            channel->u.req.resp_status = resp->status; >>>> +            complete(&channel->u.req.completion); >>>> +            break; >>>> +        case XENSND_OP_HW_PARAM_QUERY: >>>> +            channel->u.req.resp_status = resp->status; >>>> +            channel->u.req.resp.hw_param = >>>> +                    resp->resp.hw_param; >>>> +            complete(&channel->u.req.completion); >>>> +            break; >>>> + >>>> +        default: >>>> +            dev_err(&front_info->xb_dev->dev, >>>> +                "Operation %d is not supported\n", >>>> +                resp->operation); >>>> +            break; >>>> +        } >>>> +    } >>>> + >>>> +    channel->u.req.ring.rsp_cons = i; >>>> +    if (i != channel->u.req.ring.req_prod_pvt) { >>>> +        int more_to_do; >>>> + >>>> +        RING_FINAL_CHECK_FOR_RESPONSES(&channel->u.req.ring, >>>> +                           more_to_do); >>>> +        if (more_to_do) >>>> +            goto again; >>>> +    } else { >>>> +        channel->u.req.ring.sring->rsp_event = i + 1; >>>> +    } >>>> + >>>> +    spin_unlock_irqrestore(&front_info->io_lock, flags); >>>> +    return IRQ_HANDLED; >>>> +} >>>> + >>>> +static irqreturn_t evtchnl_interrupt_evt(int irq, void *dev_id) >>>> +{ >>>> +    struct xen_snd_front_evtchnl *channel = dev_id; >>>> +    struct xen_snd_front_info *front_info = channel->front_info; >>>> +    struct xensnd_event_page *page = channel->u.evt.page; >>>> +    u32 cons, prod; >>>> +    unsigned long flags; >>>> + >>>> +    if (unlikely(channel->state != EVTCHNL_STATE_CONNECTED)) >>>> +        return IRQ_HANDLED; >>>> + >>>> +    spin_lock_irqsave(&front_info->io_lock, flags); >>>> + >>>> +    prod = page->in_prod; >>>> +    /* ensure we see ring contents up to prod */ >>>> +    virt_rmb(); >>>> +    if (prod == page->in_cons) >>>> +        goto out; >>>> + >>>> +    for (cons = page->in_cons; cons != prod; cons++) { >>>> +        struct xensnd_evt *event; >>>> + >>>> +        event = &XENSND_IN_RING_REF(page, cons); >>>> +        if (unlikely(event->id != channel->evt_id++)) >>>> +            continue; >>>> + >>>> +        switch (event->type) { >>>> +        case XENSND_EVT_CUR_POS: >>>> +            /* do nothing at the moment */ >>>> +            break; >>>> +        } >>>> +    } >>>> + >>>> +    page->in_cons = cons; >>>> +    /* ensure ring contents */ >>>> +    virt_wmb(); >>>> + >>>> +out: >>>> +    spin_unlock_irqrestore(&front_info->io_lock, flags); >>>> +    return IRQ_HANDLED; >>>> +} >>>> + >>>> +void xen_snd_front_evtchnl_flush(struct xen_snd_front_evtchnl *channel) >>>> +{ >>>> +    int notify; >>>> + >>>> +    channel->u.req.ring.req_prod_pvt++; >>>> +    RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&channel->u.req.ring, notify); >>>> +    if (notify) >>>> +        notify_remote_via_irq(channel->irq); >>>> +} >>>> + >>>> +static void evtchnl_free(struct xen_snd_front_info *front_info, >>>> +             struct xen_snd_front_evtchnl *channel) >>>> +{ >>>> +    unsigned long page = 0; >>>> + >>>> +    if (channel->type == EVTCHNL_TYPE_REQ) >>>> +        page = (unsigned long)channel->u.req.ring.sring; >>>> +    else if (channel->type == EVTCHNL_TYPE_EVT) >>>> +        page = (unsigned long)channel->u.evt.page; >>>> + >>>> +    if (!page) >>>> +        return; >>>> + >>>> +    channel->state = EVTCHNL_STATE_DISCONNECTED; >>>> +    if (channel->type == EVTCHNL_TYPE_REQ) { >>>> +        /* release all who still waits for response if any */ >>>> +        channel->u.req.resp_status = -EIO; >>>> +        complete_all(&channel->u.req.completion); >>>> +    } >>>> + >>>> +    if (channel->irq) >>>> +        unbind_from_irqhandler(channel->irq, channel); >>>> + >>>> +    if (channel->port) >>>> +        xenbus_free_evtchn(front_info->xb_dev, channel->port); >>>> + >>>> +    /* end access and free the page */ >>>> +    if (channel->gref != GRANT_INVALID_REF) >>>> +        gnttab_end_foreign_access(channel->gref, 0, page); >>> Free page? >> According to [1] if page is provided to gnttab_end_foreign_access >> it will be freed. So, no need to free it manually > Either a free_page() is missing here in an else clause or the if is > not necessary. Good catch ;) I need else + free_page, because I won't be able to end access for invalid grant ref. Thank you > > Juergen