Received: by 10.223.185.116 with SMTP id b49csp605691wrg; Wed, 21 Feb 2018 04:02:32 -0800 (PST) X-Google-Smtp-Source: AH8x226emv1alhn8AE99n4pbw+YXY/aPTm0vBTSjykSQPjloWgv+CGZCjtxOVH4m/0Dk+kqxYuB9 X-Received: by 10.101.65.203 with SMTP id b11mr535920pgq.118.1519214551963; Wed, 21 Feb 2018 04:02:31 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519214551; cv=none; d=google.com; s=arc-20160816; b=fn6EOzf55/6PFp9sB/35QiSAgF8VPbrTztZaG9ZgvAiXNRcw4jf8Z2aB8DDTV7Xu9P BScOkjki5ecSChfPzQPMyezHeuJYUO895HYyTMb018vXWZEKSlsUAnAH6L4O+iyC1lYO ocGVNiFtkA3Tpb3iDBILKow27P1pFHc/XbdR3sNLqkiTkXOCTb9qtQwxVyEbDVFqd50+ mNUGQ3voldB60Lou37osEJigvRW9crOPObjGPlDZ6XSlhrgW9FiULSmr/kdt4Q6RiPim f8tK4dWgFzHLts0nnjE+sj+RY7riuh6pKfk/U1KCwaapUgoAgx3QZnjDN1cY6AQhMWvA m5hg== 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=Po1gQO4wlPd8OrIEspvu7Ml1jtKII70gW9PdZjQhl9I=; b=QihlR9p1zi6a1e3AxoPI72+xPC3yDxqOfjVud7NeuensyjohlqTE0RRv5zjCU94f7y hvDWPPvAgIYnceLZrGKzGtHH2t0bDjgOT9EJH6UmtjBsHEnJLG6ut0NidNU8vMyg4DFd roEIWgUmOGhILyPYcMr6a5v72992qp+RXUH5o6k1sAkdPvBpWgTr9Cj6k9Jb/SPFbCG8 KYro3QvaNOcAooz6IzEQpJMN7TEzoamYC0es9Lnrkj7roJJ+EJgjk+fkuoKIX2cEvkLh j+BNe2PGsCjSoGI8e3f58izTzS6B3lx5m89jRabfApE3CfB6q5rTMXdPSFnPKtbg4trG jNTw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=I7EaLbD9; 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 o3si1066372pgn.642.2018.02.21.04.02.12; Wed, 21 Feb 2018 04:02:31 -0800 (PST) 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=I7EaLbD9; 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 S1752014AbeBUIE1 (ORCPT + 99 others); Wed, 21 Feb 2018 03:04:27 -0500 Received: from mail-lf0-f65.google.com ([209.85.215.65]:35418 "EHLO mail-lf0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751983AbeBUIEI (ORCPT ); Wed, 21 Feb 2018 03:04:08 -0500 Received: by mail-lf0-f65.google.com with SMTP id 70so1077609lfw.2 for ; Wed, 21 Feb 2018 00:04:07 -0800 (PST) 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=Po1gQO4wlPd8OrIEspvu7Ml1jtKII70gW9PdZjQhl9I=; b=I7EaLbD9DXwpvDNM/BZhQR503ZcmZM094Ry3jRId8rvfzXlmdWOImhpcnb9tGxe7Zm cWrKnt06HQMp6IjhLGeaocAYvD+HtpR8AQ4LxleQRTDa6Of70gCU0MDaSdVD8MsQCco0 jr/V+g+fLfhB4HU7YWJIe7ZMTQwxZcwEKCDPHHffu7HAC+nWtqpFRiK0H/i5TRq+St3a rqu4iC4H4NRLky5BcRVkx+NRd0+vmvXIrbRFOsNOIBOUaQ2L1Yhl6A/86/0MMopus9lW ga18lmMLJZCe28+4QejDQBsdsVYqPMLbbgPA0HJ6thjrCZwciUb8TLl7qBJgSabvSBHW Tpnw== 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=Po1gQO4wlPd8OrIEspvu7Ml1jtKII70gW9PdZjQhl9I=; b=gO694hDFwNV8YqXf3dODEL6k3kkG9FR40VedRhS+XK/2/E6Ktvt75FMEG0GuswHi2K +5CHiwoqbuDPDBALChvS5RA5IxQLBEUkK/ACey4QAS36geJLfPepa1skOHUPTjLggK17 Rlr5IHb8hFKOgY8zNGHfBfpVmcGtCMZHrbzP4JKHwLGrTcxcPUI1O6rMnpa20BWrFWpN J4xqcmVVLZeKOm7YfyrqOhlpSjXqoYP1mE2XhZHvcWR+t390PrMzsyfh28Su5bpaez9J hgoMZvNjM+icl/jXOXKM6AVH5CWXdlJ+kp5AIWI8kaOkRISDq3xHOxb0Iz1kFMy+QihU oc0A== X-Gm-Message-State: APf1xPAtPp33UYpnU6pC+vQVZuejCouY/raDlSH/bASGZJ3cbbktO8qP CtHJXobbi7RYz2KMEwq2bMs= X-Received: by 10.25.219.8 with SMTP id s8mr1796048lfg.31.1519200246969; Wed, 21 Feb 2018 00:04:06 -0800 (PST) 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 g38sm687394lji.24.2018.02.21.00.04.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 21 Feb 2018 00:04:06 -0800 (PST) From: Oleksandr Andrushchenko To: xen-devel@lists.xenproject.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, airlied@linux.ie, daniel.vetter@intel.com, seanpaul@chromium.org, gustavo@padovan.org, jgross@suse.com, boris.ostrovsky@oracle.com, konrad.wilk@oracle.com Cc: andr2000@gmail.com, Oleksandr Andrushchenko Subject: [PATCH 9/9] drm/xen-front: Implement communication with backend Date: Wed, 21 Feb 2018 10:03:42 +0200 Message-Id: <1519200222-20623-10-git-send-email-andr2000@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1519200222-20623-1-git-send-email-andr2000@gmail.com> References: <1519200222-20623-1-git-send-email-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 Handle communication with the backend: - send requests and wait for the responses according to the displif protocol - serialize access to the communication channel - time-out used for backend communication is set to 3000 ms - manage display buffers shared with the backend Signed-off-by: Oleksandr Andrushchenko --- drivers/gpu/drm/xen/xen_drm_front.c | 327 +++++++++++++++++++++++++++++++++++- drivers/gpu/drm/xen/xen_drm_front.h | 5 + 2 files changed, 327 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/xen/xen_drm_front.c b/drivers/gpu/drm/xen/xen_drm_front.c index 8de88e359d5e..5ad546231d30 100644 --- a/drivers/gpu/drm/xen/xen_drm_front.c +++ b/drivers/gpu/drm/xen/xen_drm_front.c @@ -31,12 +31,146 @@ #include "xen_drm_front_evtchnl.h" #include "xen_drm_front_shbuf.h" +/* timeout in ms to wait for backend to respond */ +#define VDRM_WAIT_BACK_MS 3000 + +struct xen_drm_front_dbuf { + struct list_head list; + uint64_t dbuf_cookie; + uint64_t fb_cookie; + struct xen_drm_front_shbuf *shbuf; +}; + +static int dbuf_add_to_list(struct xen_drm_front_info *front_info, + struct xen_drm_front_shbuf *shbuf, uint64_t dbuf_cookie) +{ + struct xen_drm_front_dbuf *dbuf; + + dbuf = kzalloc(sizeof(*dbuf), GFP_KERNEL); + if (!dbuf) + return -ENOMEM; + + dbuf->dbuf_cookie = dbuf_cookie; + dbuf->shbuf = shbuf; + list_add(&dbuf->list, &front_info->dbuf_list); + return 0; +} + +static struct xen_drm_front_dbuf *dbuf_get(struct list_head *dbuf_list, + uint64_t dbuf_cookie) +{ + struct xen_drm_front_dbuf *buf, *q; + + list_for_each_entry_safe(buf, q, dbuf_list, list) + if (buf->dbuf_cookie == dbuf_cookie) + return buf; + + return NULL; +} + +static void dbuf_flush_fb(struct list_head *dbuf_list, uint64_t fb_cookie) +{ + struct xen_drm_front_dbuf *buf, *q; + + list_for_each_entry_safe(buf, q, dbuf_list, list) + if (buf->fb_cookie == fb_cookie) + xen_drm_front_shbuf_flush(buf->shbuf); +} + +static void dbuf_free(struct list_head *dbuf_list, uint64_t dbuf_cookie) +{ + struct xen_drm_front_dbuf *buf, *q; + + list_for_each_entry_safe(buf, q, dbuf_list, list) + if (buf->dbuf_cookie == dbuf_cookie) { + list_del(&buf->list); + xen_drm_front_shbuf_unmap(buf->shbuf); + xen_drm_front_shbuf_free(buf->shbuf); + kfree(buf); + break; + } +} + +static void dbuf_free_all(struct list_head *dbuf_list) +{ + struct xen_drm_front_dbuf *buf, *q; + + list_for_each_entry_safe(buf, q, dbuf_list, list) { + list_del(&buf->list); + xen_drm_front_shbuf_unmap(buf->shbuf); + xen_drm_front_shbuf_free(buf->shbuf); + kfree(buf); + } +} + +static struct xendispl_req *be_prepare_req( + struct xen_drm_front_evtchnl *evtchnl, uint8_t operation) +{ + struct xendispl_req *req; + + req = RING_GET_REQUEST(&evtchnl->u.req.ring, + evtchnl->u.req.ring.req_prod_pvt); + req->operation = operation; + req->id = evtchnl->evt_next_id++; + evtchnl->evt_id = req->id; + return req; +} + +static int be_stream_do_io(struct xen_drm_front_evtchnl *evtchnl, + struct xendispl_req *req) +{ + reinit_completion(&evtchnl->u.req.completion); + if (unlikely(evtchnl->state != EVTCHNL_STATE_CONNECTED)) + return -EIO; + + xen_drm_front_evtchnl_flush(evtchnl); + return 0; +} + +static int be_stream_wait_io(struct xen_drm_front_evtchnl *evtchnl) +{ + if (wait_for_completion_timeout(&evtchnl->u.req.completion, + msecs_to_jiffies(VDRM_WAIT_BACK_MS)) <= 0) + return -ETIMEDOUT; + + return evtchnl->u.req.resp_status; +} + static int be_mode_set(struct xen_drm_front_drm_pipeline *pipeline, uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint32_t bpp, uint64_t fb_cookie) { - return 0; + struct xen_drm_front_evtchnl *evtchnl; + struct xen_drm_front_info *front_info; + struct xendispl_req *req; + unsigned long flags; + int ret; + + front_info = pipeline->drm_info->front_info; + evtchnl = &front_info->evt_pairs[pipeline->index].req; + if (unlikely(!evtchnl)) + return -EIO; + + mutex_lock(&front_info->req_io_lock); + + spin_lock_irqsave(&front_info->io_lock, flags); + req = be_prepare_req(evtchnl, XENDISPL_OP_SET_CONFIG); + req->op.set_config.x = x; + req->op.set_config.y = y; + req->op.set_config.width = width; + req->op.set_config.height = height; + req->op.set_config.bpp = bpp; + req->op.set_config.fb_cookie = fb_cookie; + + ret = be_stream_do_io(evtchnl, req); + spin_unlock_irqrestore(&front_info->io_lock, flags); + + if (ret == 0) + ret = be_stream_wait_io(evtchnl); + + mutex_unlock(&front_info->req_io_lock); + return ret; } static int be_dbuf_create_int(struct xen_drm_front_info *front_info, @@ -44,7 +178,69 @@ static int be_dbuf_create_int(struct xen_drm_front_info *front_info, uint32_t bpp, uint64_t size, struct page **pages, struct sg_table *sgt) { + struct xen_drm_front_evtchnl *evtchnl; + struct xen_drm_front_shbuf *shbuf; + struct xendispl_req *req; + struct xen_drm_front_shbuf_cfg buf_cfg; + unsigned long flags; + int ret; + + evtchnl = &front_info->evt_pairs[GENERIC_OP_EVT_CHNL].req; + if (unlikely(!evtchnl)) + return -EIO; + + memset(&buf_cfg, 0, sizeof(buf_cfg)); + buf_cfg.xb_dev = front_info->xb_dev; + buf_cfg.pages = pages; + buf_cfg.size = size; + buf_cfg.sgt = sgt; + buf_cfg.be_alloc = front_info->cfg.be_alloc; + + shbuf = xen_drm_front_shbuf_alloc(&buf_cfg); + if (!shbuf) + return -ENOMEM; + + ret = dbuf_add_to_list(front_info, shbuf, dbuf_cookie); + if (ret < 0) { + xen_drm_front_shbuf_free(shbuf); + return ret; + } + + mutex_lock(&front_info->req_io_lock); + + spin_lock_irqsave(&front_info->io_lock, flags); + req = be_prepare_req(evtchnl, XENDISPL_OP_DBUF_CREATE); + req->op.dbuf_create.gref_directory = + xen_drm_front_shbuf_get_dir_start(shbuf); + req->op.dbuf_create.buffer_sz = size; + req->op.dbuf_create.dbuf_cookie = dbuf_cookie; + req->op.dbuf_create.width = width; + req->op.dbuf_create.height = height; + req->op.dbuf_create.bpp = bpp; + if (buf_cfg.be_alloc) + req->op.dbuf_create.flags |= XENDISPL_DBUF_FLG_REQ_ALLOC; + + ret = be_stream_do_io(evtchnl, req); + spin_unlock_irqrestore(&front_info->io_lock, flags); + + if (ret < 0) + goto fail; + + ret = be_stream_wait_io(evtchnl); + if (ret < 0) + goto fail; + + ret = xen_drm_front_shbuf_map(shbuf); + if (ret < 0) + goto fail; + + mutex_unlock(&front_info->req_io_lock); return 0; + +fail: + mutex_unlock(&front_info->req_io_lock); + dbuf_free(&front_info->dbuf_list, dbuf_cookie); + return ret; } static int be_dbuf_create_from_sgt(struct xen_drm_front_info *front_info, @@ -66,26 +262,144 @@ static int be_dbuf_create_from_pages(struct xen_drm_front_info *front_info, static int be_dbuf_destroy(struct xen_drm_front_info *front_info, uint64_t dbuf_cookie) { - return 0; + struct xen_drm_front_evtchnl *evtchnl; + struct xendispl_req *req; + unsigned long flags; + bool be_alloc; + int ret; + + evtchnl = &front_info->evt_pairs[GENERIC_OP_EVT_CHNL].req; + if (unlikely(!evtchnl)) + return -EIO; + + be_alloc = front_info->cfg.be_alloc; + + /* + * for the backend allocated buffer release references now, so backend + * can free the buffer + */ + if (be_alloc) + dbuf_free(&front_info->dbuf_list, dbuf_cookie); + + mutex_lock(&front_info->req_io_lock); + + spin_lock_irqsave(&front_info->io_lock, flags); + req = be_prepare_req(evtchnl, XENDISPL_OP_DBUF_DESTROY); + req->op.dbuf_destroy.dbuf_cookie = dbuf_cookie; + + ret = be_stream_do_io(evtchnl, req); + spin_unlock_irqrestore(&front_info->io_lock, flags); + + if (ret == 0) + ret = be_stream_wait_io(evtchnl); + + /* + * do this regardless of communication status with the backend: + * if we cannot remove remote resources remove what we can locally + */ + if (!be_alloc) + dbuf_free(&front_info->dbuf_list, dbuf_cookie); + + mutex_unlock(&front_info->req_io_lock); + return ret; } static int be_fb_attach(struct xen_drm_front_info *front_info, uint64_t dbuf_cookie, uint64_t fb_cookie, uint32_t width, uint32_t height, uint32_t pixel_format) { - return 0; + struct xen_drm_front_evtchnl *evtchnl; + struct xen_drm_front_dbuf *buf; + struct xendispl_req *req; + unsigned long flags; + int ret; + + evtchnl = &front_info->evt_pairs[GENERIC_OP_EVT_CHNL].req; + if (unlikely(!evtchnl)) + return -EIO; + + buf = dbuf_get(&front_info->dbuf_list, dbuf_cookie); + if (!buf) + return -EINVAL; + + buf->fb_cookie = fb_cookie; + + mutex_lock(&front_info->req_io_lock); + + spin_lock_irqsave(&front_info->io_lock, flags); + req = be_prepare_req(evtchnl, XENDISPL_OP_FB_ATTACH); + req->op.fb_attach.dbuf_cookie = dbuf_cookie; + req->op.fb_attach.fb_cookie = fb_cookie; + req->op.fb_attach.width = width; + req->op.fb_attach.height = height; + req->op.fb_attach.pixel_format = pixel_format; + + ret = be_stream_do_io(evtchnl, req); + spin_unlock_irqrestore(&front_info->io_lock, flags); + + if (ret == 0) + ret = be_stream_wait_io(evtchnl); + + mutex_unlock(&front_info->req_io_lock); + return ret; } static int be_fb_detach(struct xen_drm_front_info *front_info, uint64_t fb_cookie) { - return 0; + struct xen_drm_front_evtchnl *evtchnl; + struct xendispl_req *req; + unsigned long flags; + int ret; + + evtchnl = &front_info->evt_pairs[GENERIC_OP_EVT_CHNL].req; + if (unlikely(!evtchnl)) + return -EIO; + + mutex_lock(&front_info->req_io_lock); + + spin_lock_irqsave(&front_info->io_lock, flags); + req = be_prepare_req(evtchnl, XENDISPL_OP_FB_DETACH); + req->op.fb_detach.fb_cookie = fb_cookie; + + ret = be_stream_do_io(evtchnl, req); + spin_unlock_irqrestore(&front_info->io_lock, flags); + + if (ret == 0) + ret = be_stream_wait_io(evtchnl); + + mutex_unlock(&front_info->req_io_lock); + return ret; } static int be_page_flip(struct xen_drm_front_info *front_info, int conn_idx, uint64_t fb_cookie) { - return 0; + struct xen_drm_front_evtchnl *evtchnl; + struct xendispl_req *req; + unsigned long flags; + int ret; + + if (unlikely(conn_idx >= front_info->num_evt_pairs)) + return -EINVAL; + + dbuf_flush_fb(&front_info->dbuf_list, fb_cookie); + evtchnl = &front_info->evt_pairs[conn_idx].req; + + mutex_lock(&front_info->req_io_lock); + + spin_lock_irqsave(&front_info->io_lock, flags); + req = be_prepare_req(evtchnl, XENDISPL_OP_PG_FLIP); + req->op.pg_flip.fb_cookie = fb_cookie; + + ret = be_stream_do_io(evtchnl, req); + spin_unlock_irqrestore(&front_info->io_lock, flags); + + if (ret == 0) + ret = be_stream_wait_io(evtchnl); + + mutex_unlock(&front_info->req_io_lock); + return ret; } static void xen_drm_drv_unload(struct xen_drm_front_info *front_info) @@ -183,6 +497,7 @@ static void xen_drv_remove_internal(struct xen_drm_front_info *front_info) { xen_drm_drv_deinit(front_info); xen_drm_front_evtchnl_free_all(front_info); + dbuf_free_all(&front_info->dbuf_list); } static int backend_on_initwait(struct xen_drm_front_info *front_info) @@ -310,6 +625,8 @@ static int xen_drv_probe(struct xenbus_device *xb_dev, front_info->xb_dev = xb_dev; spin_lock_init(&front_info->io_lock); + mutex_init(&front_info->req_io_lock); + INIT_LIST_HEAD(&front_info->dbuf_list); front_info->drm_pdrv_registered = false; dev_set_drvdata(&xb_dev->dev, front_info); return xenbus_switch_state(xb_dev, XenbusStateInitialising); diff --git a/drivers/gpu/drm/xen/xen_drm_front.h b/drivers/gpu/drm/xen/xen_drm_front.h index c6f52c892434..db32d00145d1 100644 --- a/drivers/gpu/drm/xen/xen_drm_front.h +++ b/drivers/gpu/drm/xen/xen_drm_front.h @@ -137,6 +137,8 @@ struct xen_drm_front_info { struct xenbus_device *xb_dev; /* to protect data between backend IO code and interrupt handler */ spinlock_t io_lock; + /* serializer for backend IO: request/response */ + struct mutex req_io_lock; bool drm_pdrv_registered; /* virtual DRM platform device */ struct platform_device *drm_pdev; @@ -144,6 +146,9 @@ struct xen_drm_front_info { int num_evt_pairs; struct xen_drm_front_evtchnl_pair *evt_pairs; struct xen_drm_front_cfg cfg; + + /* display buffers */ + struct list_head dbuf_list; }; #endif /* __XEN_DRM_FRONT_H_ */ -- 2.7.4