drm/xen-front: Add support for Xen PV display frontend
Subsystems (3)
cover drm/xen-front: Add support for Xen PV display frontend
From: Oleksandr Andrushchenko <[email protected]>
Hello!
This patch series adds support for Xen [1] para-virtualized frontend display driver. It implements the protocol from include/xen/interface/io/displif.h [2].
Accompanying backend [3] is implemented as a user-space application and its helper library [4], capable of running as a Weston client or DRM master.
Configuration of both backend and frontend is done via Xen guest domain configuration options [5].
*******************************************************************************
* Driver limitations
*******************************************************************************
1. Configuration options 1.1 (contiguous display buffers) and 2 (backend allocated buffers) below are not supported at the same time.
2. Only primary plane without additional properties is supported.
3. Only one video mode supported which resolution is configured via XenStore.
4. All CRTCs operate at fixed frequency of 60Hz.
*******************************************************************************
* Driver modes of operation in terms of display buffers used
*******************************************************************************
Depending on the requirements for the para-virtualized environment, namely requirements dictated by the accompanying DRM/(v)GPU drivers running in both host and guest environments, number of operating modes of para-virtualized display driver are supported:
- display buffers can be allocated by either frontend driver or backend
- display buffers can be allocated to be contiguous in memory or not
Note! Frontend driver itself has no dependency on contiguous memory for
its operation.
*******************************************************************************
* 1. Buffers allocated by the frontend driver.
*******************************************************************************
The below modes of operation are configured at compile-time via frontend driver's kernel configuration.
1.1. Front driver configured to use GEM CMA helpers
This use-case is useful when used with accompanying DRM/vGPU driver in guest domain which was designed to only work with contiguous buffers, e.g. DRM driver based on GEM CMA helpers: such drivers can only import contiguous PRIME buffers, thus requiring frontend driver to provide such. In order to implement this mode of operation para-virtualized frontend driver can be configured to use GEM CMA helpers.
1.2. Front driver doesn't use GEM CMA
If accompanying drivers can cope with non-contiguous memory then, to lower pressure on CMA subsystem of the kernel, driver can allocate buffers from system memory.
Note! If used with accompanying DRM/(v)GPU drivers this mode of operation
may require IOMMU support on the platform, so accompanying DRM/vGPU hardware can still reach display buffer memory while importing PRIME buffers from the frontend driver.
*******************************************************************************
* 2. Buffers allocated by the backend
*******************************************************************************
This mode of operation is run-time configured via guest domain configuration through XenStore entries.
For systems which do not provide IOMMU support, but having specific requirements for display buffers it is possible to allocate such buffers at backend side and share those with the frontend.
For example, if host domain is 1:1 mapped and has DRM/GPU hardware expecting physically contiguous memory, this allows implementing zero-copying use-cases.
I would like to thank at least, but not at last the following people/communities who helped this driver to happen ;)
1. My team at EPAM for continuous support
2. Xen community for answering tons of questions on different modes of operation of the driver with respect to virtualized environment.
3. Rob Clark for "GEM allocation for para-virtualized DRM driver" [6]
4. Maarten Lankhorst for "Atomic driver and old remove FB behavior" [7]
5. Ville Syrjälä for "Questions on page flips and atomic modeset" [8]
Thank you,
Oleksandr Andrushchenko
P.S. There are two dependencies for this driver limiting some of the use-cases which are on review now:
1. "drm/simple_kms_helper: Add {enable|disable}_vblank callback support" [9]
2. "drm/simple_kms_helper: Fix NULL pointer dereference with no active CRTC" [10]
[1] https://wiki.xen.org/wiki/Paravirtualization_(PV)#PV_IO_Drivers
[2] https://elixir.bootlin.com/linux/v4.16-rc2/source/include/xen/interface/io/displif.h
[3] https://github.com/xen-troops/displ_be
[4] https://github.com/xen-troops/libxenbe
[5] https://xenbits.xen.org/gitweb/?p=xen.git;a=blob;f=docs/man/xl.cfg.pod.5.in;h=a699367779e2ae1212ff8f638eff0206ec1a1cc9;hb=refs/heads/master#l1257
[6] https://lists.freedesktop.org/archives/dri-devel/2017-March/136038.html
[7] https://www.spinics.net/lists/dri-devel/msg164102.html
[8] https://www.spinics.net/lists/dri-devel/msg164463.html
[9] https://patchwork.freedesktop.org/series/38073/
[10] https://patchwork.freedesktop.org/series/38139/
Oleksandr Andrushchenko (9):
drm/xen-front: Introduce Xen para-virtualized frontend driver drm/xen-front: Implement Xen bus state handling drm/xen-front: Read driver configuration from Xen store drm/xen-front: Implement Xen event channel handling drm/xen-front: Implement handling of shared display buffers drm/xen-front: Introduce DRM/KMS virtual display driver drm/xen-front: Implement KMS/connector handling drm/xen-front: Implement GEM operations drm/xen-front: Implement communication with backend
drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/xen/Kconfig | 30 ++ drivers/gpu/drm/xen/Makefile | 17 + drivers/gpu/drm/xen/xen_drm_front.c | 712 ++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front.h | 154 ++++++ drivers/gpu/drm/xen/xen_drm_front_cfg.c | 84 ++++ drivers/gpu/drm/xen/xen_drm_front_cfg.h | 45 ++ drivers/gpu/drm/xen/xen_drm_front_conn.c | 125 +++++ drivers/gpu/drm/xen/xen_drm_front_conn.h | 35 ++ drivers/gpu/drm/xen/xen_drm_front_drv.c | 294 ++++++++++++ drivers/gpu/drm/xen/xen_drm_front_drv.h | 73 +++ drivers/gpu/drm/xen/xen_drm_front_evtchnl.c | 399 ++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_evtchnl.h | 89 ++++ drivers/gpu/drm/xen/xen_drm_front_gem.c | 360 ++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_gem.h | 46 ++ drivers/gpu/drm/xen/xen_drm_front_gem_cma.c | 93 ++++ drivers/gpu/drm/xen/xen_drm_front_kms.c | 299 ++++++++++++ drivers/gpu/drm/xen/xen_drm_front_kms.h | 30 ++ drivers/gpu/drm/xen/xen_drm_front_shbuf.c | 430 +++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_shbuf.h | 80 ++++ 21 files changed, 3398 insertions(+) create mode 100644 drivers/gpu/drm/xen/Kconfig create mode 100644 drivers/gpu/drm/xen/Makefile create mode 100644 drivers/gpu/drm/xen/xen_drm_front.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front.h create mode 100644 drivers/gpu/drm/xen/xen_drm_front_cfg.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_cfg.h create mode 100644 drivers/gpu/drm/xen/xen_drm_front_conn.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_conn.h create mode 100644 drivers/gpu/drm/xen/xen_drm_front_drv.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_drv.h create mode 100644 drivers/gpu/drm/xen/xen_drm_front_evtchnl.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_evtchnl.h create mode 100644 drivers/gpu/drm/xen/xen_drm_front_gem.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_gem.h create mode 100644 drivers/gpu/drm/xen/xen_drm_front_gem_cma.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_kms.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_kms.h create mode 100644 drivers/gpu/drm/xen/xen_drm_front_shbuf.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_shbuf.h
Signature · 6 lines
2.7.4 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 1/9 drm/xen-front: Introduce Xen para-virtualized frontend driver
From: Oleksandr Andrushchenko <[email protected]>
Introduce skeleton of the para-virtualized Xen display frontend driver. This patch only adds required essential stubs.
--- drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/xen/Kconfig | 17 ++++++++ drivers/gpu/drm/xen/Makefile | 5 +++ drivers/gpu/drm/xen/xen_drm_front.c | 83 +++++++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+) create mode 100644 drivers/gpu/drm/xen/Kconfig create mode 100644 drivers/gpu/drm/xen/Makefile create mode 100644 drivers/gpu/drm/xen/xen_drm_front.c
drivers/gpu/drm/Kconfig +2 -0
@@ -289,6 +289,8 @@ source "drivers/gpu/drm/pl111/Kconfig" source "drivers/gpu/drm/tve200/Kconfig" +source "drivers/gpu/drm/xen/Kconfig" + # Keep legacy drivers last menuconfig DRM_LEGACY
drivers/gpu/drm/Makefile +1 -0
@@ -103,3 +103,4 @@ obj-$(CONFIG_DRM_MXSFB) += mxsfb/ obj-$(CONFIG_DRM_TINYDRM) += tinydrm/ obj-$(CONFIG_DRM_PL111) += pl111/ obj-$(CONFIG_DRM_TVE200) += tve200/ +obj-$(CONFIG_DRM_XEN) += xen/
drivers/gpu/drm/xen/Kconfig new file +17 -0
@@ -0,0 +1,17 @@ +config DRM_XEN + bool "DRM Support for Xen guest OS" + depends on XEN + help + Choose this option if you want to enable DRM support + for Xen. + +config DRM_XEN_FRONTEND + tristate "Para-virtualized frontend driver for Xen guest OS" + depends on DRM_XEN + depends on DRM + select DRM_KMS_HELPER + select VIDEOMODE_HELPERS + select XEN_XENBUS_FRONTEND + help + Choose this option if you want to enable a para-virtualized + frontend DRM/KMS driver for Xen guest OSes.
drivers/gpu/drm/xen/Makefile new file +5 -0
@@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 + +drm_xen_front-objs := xen_drm_front.o + +obj-$(CONFIG_DRM_XEN_FRONTEND) += drm_xen_front.o
drivers/gpu/drm/xen/xen_drm_front.c new file +83 -0
83 lines not on this page · raw message
Signature · 6 lines
2.7.4 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/9] drm/xen-front: Introduce Xen para-virtualized frontend driver
Quoted 82 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Introduce skeleton of the para-virtualized Xen display frontend driver. This patch only adds required essential stubs.
Signed-off-by Oleksandr Andrushchenko <[email protected]>--- drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/xen/Kconfig | 17 ++++++++ drivers/gpu/drm/xen/Makefile | 5 +++ drivers/gpu/drm/xen/xen_drm_front.c | 83 +++++++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+) create mode 100644 drivers/gpu/drm/xen/Kconfig create mode 100644 drivers/gpu/drm/xen/Makefile create mode 100644 drivers/gpu/drm/xen/xen_drm_front.cdrivers/gpu/drm/Kconfig +2
-0@@ -289,6 +289,8 @@ source "drivers/gpu/drm/pl111/Kconfig" source "drivers/gpu/drm/tve200/Kconfig" +source "drivers/gpu/drm/xen/Kconfig" + # Keep legacy drivers last menuconfig DRM_LEGACYdrivers/gpu/drm/Makefile +1
-0@@ -103,3 +103,4 @@ obj-$(CONFIG_DRM_MXSFB) += mxsfb/ obj-$(CONFIG_DRM_TINYDRM) += tinydrm/ obj-$(CONFIG_DRM_PL111) += pl111/ obj-$(CONFIG_DRM_TVE200) += tve200/ +obj-$(CONFIG_DRM_XEN) += xen/drivers/gpu/drm/xen/Kconfig new file +17
-0@@ -0,0 +1,17 @@ +config DRM_XEN + bool "DRM Support for Xen guest OS" + depends on XEN + help + Choose this option if you want to enable DRM support + for Xen. + +config DRM_XEN_FRONTEND + tristate "Para-virtualized frontend driver for Xen guest OS" + depends on DRM_XEN + depends on DRM + select DRM_KMS_HELPER + select VIDEOMODE_HELPERS + select XEN_XENBUS_FRONTEND + help + Choose this option if you want to enable a para-virtualized + frontend DRM/KMS driver for Xen guest OSes.drivers/gpu/drm/xen/Makefile new file +5
-0@@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 + +drm_xen_front-objs := xen_drm_front.o + +obj-$(CONFIG_DRM_XEN_FRONTEND) += drm_xen_front.odrivers/gpu/drm/xen/xen_drm_front.c new file +2
-0@@ -0,0 +1,83 @@ +/* +* Xen para-virtual DRM device
drivers/gpu/drm/xen/xen_drm_front.c line 12
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front.c new file +10
-0+* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details.
Use SPDX identifier instead (same applies for all other new sources):
// SPDX-License-Identifier: GPL-2.0
Quoted 41 lines
drivers/gpu/drm/xen/xen_drm_front.c new file +41
-0+* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include <drm/drmP.h> + +#include <xen/platform_pci.h> +#include <xen/xen.h> +#include <xen/xenbus.h> + +#include <xen/interface/io/displif.h> + +static void backend_on_changed (struct xenbus_device *xb_dev, +enum xenbus_state backend_state) +{ +} + +static int xen_drv_probe (struct xenbus_device *xb_dev, +const struct xenbus_device_id *id) +{ +return 0 ; +} + +static int xen_drv_remove (struct xenbus_device *dev) +{ +return 0 ; +} + +static const struct xenbus_device_id xen_drv_ids[] = { + {XENDISPL_DRIVER_NAME }, + {"" } +}; + +static struct xenbus_driver xen_driver = { + .ids = xen_drv_ids, + .probe = xen_drv_probe, + .remove = xen_drv_remove, + .otherend_changed = backend_on_changed, +};
drivers/gpu/drm/xen/xen_drm_front.c line 63
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front.c new file +10
-0+ +static int __init xen_drv_init (void ) +{ +if (!xen_domain ()) +return -ENODEV ; + +if (xen_initial_domain ()) { +DRM_ERROR (XENDISPL_DRIVER_NAME " cannot run in initial domain\n" ); +return -ENODEV ; + }
Why not? Wouldn't that be possible in case of the backend living in a driver domain?
Juergen
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Re: [PATCH 1/9] drm/xen-front: Introduce Xen para-virtualized frontend driver
Quoted 96 lines · Juergen Gross
Quoted 82 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Introduce skeleton of the para-virtualized Xen display frontend driver. This patch only adds required essential stubs.
Signed-off-by Oleksandr Andrushchenko <[email protected]>--- drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/xen/Kconfig | 17 ++++++++ drivers/gpu/drm/xen/Makefile | 5 +++ drivers/gpu/drm/xen/xen_drm_front.c | 83 +++++++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+)create mode 100644
drivers/gpu/drm/xen/Kconfigcreate mode 100644drivers/gpu/drm/xen/Makefilecreate mode 100644drivers/gpu/drm/xen/xen_drm_front.cdrivers/gpu/drm/Kconfig +2
-0@@ -289,6 +289,8 @@ source "drivers/gpu/drm/pl111/Kconfig" source "drivers/gpu/drm/tve200/Kconfig" +source "drivers/gpu/drm/xen/Kconfig" + # Keep legacy drivers last menuconfig DRM_LEGACYdrivers/gpu/drm/Makefile +1
-0@@ -103,3 +103,4 @@ obj-$(CONFIG_DRM_MXSFB) += mxsfb/ obj-$(CONFIG_DRM_TINYDRM) += tinydrm/ obj-$(CONFIG_DRM_PL111) += pl111/ obj-$(CONFIG_DRM_TVE200) += tve200/ +obj-$(CONFIG_DRM_XEN) += xen/drivers/gpu/drm/xen/Kconfig new file +17
-0@@ -0,0 +1,17 @@ +config DRM_XEN + bool "DRM Support for Xen guest OS" + depends on XEN + help + Choose this option if you want to enable DRM support + for Xen. + +config DRM_XEN_FRONTEND + tristate "Para-virtualized frontend driver for Xen guest OS" + depends on DRM_XEN + depends on DRM + select DRM_KMS_HELPER + select VIDEOMODE_HELPERS + select XEN_XENBUS_FRONTEND + help + Choose this option if you want to enable a para-virtualized + frontend DRM/KMS driver for Xen guest OSes.drivers/gpu/drm/xen/Makefile new file +5
-0@@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 + +drm_xen_front-objs := xen_drm_front.o + +obj-$(CONFIG_DRM_XEN_FRONTEND) += drm_xen_front.odrivers/gpu/drm/xen/xen_drm_front.c new file +2
-0@@ -0,0 +1,83 @@ +/* +* Xen para-virtual DRM device drivers/gpu/drm/xen/xen_drm_front.c line 12
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front.c new file +10
-0+* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. Use SPDX identifier instead (same applies for all other new sources):
Quoted 1 line
// SPDX-License-Identifier: GPL-2.0
Will update, thank you
Quoted 45 lines
Quoted 45 lines
drivers/gpu/drm/xen/xen_drm_front.c new file +45
-0+* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include <drm/drmP.h> + +#include <xen/platform_pci.h> +#include <xen/xen.h> +#include <xen/xenbus.h> + +#include <xen/interface/io/displif.h> + +static void backend_on_changed (struct xenbus_device *xb_dev, +enum xenbus_state backend_state) +{ +} + +static int xen_drv_probe (struct xenbus_device *xb_dev, +const struct xenbus_device_id *id) +{ +return 0 ; +} + +static int xen_drv_remove (struct xenbus_device *dev) +{ +return 0 ; +} + +static const struct xenbus_device_id xen_drv_ids[] = { + {XENDISPL_DRIVER_NAME }, + {"" } +}; + +static struct xenbus_driver xen_driver = { + .ids = xen_drv_ids, + .probe = xen_drv_probe, + .remove = xen_drv_remove, + .otherend_changed = backend_on_changed, +}; + +static int __init xen_drv_init (void ) +{ +if (!xen_domain ())
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front.c line 63
Quoted 6 lines
drivers/gpu/drm/xen/xen_drm_front.c new file +6
-0+return -ENODEV ; + +if (xen_initial_domain ()) { +DRM_ERROR (XENDISPL_DRIVER_NAME " cannot run in initial domain\n" ); +return -ENODEV ; + }Why not? Wouldn't that be possible in case of the backend living in a driver domain?
It is possible (and in my use-case backend indeed runs in a driver domain). I was just not sure if it is really a good idea to allow that. If you think this is ok, then I'll remove this check
Quoted 2 lines
Juergen
Thank you,
Oleksandr
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/9] drm/xen-front: Introduce Xen para-virtualized frontend driver
Quoted 155 lines · Oleksandr Andrushchenko
Quoted 98 lines · Juergen Gross
Quoted 86 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Introduce skeleton of the para-virtualized Xen display frontend driver. This patch only adds required essential stubs.
Signed-off-by: Oleksandr Andrushchenko <[email protected]>
---
drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/xen/Kconfig | 17 ++++++++ drivers/gpu/drm/xen/Makefile | 5 +++drivers/gpu/drm/xen/xen_drm_front.c| 83
+++++++++++++++++++++++++++++++++++++5 files changed, 108 insertions(+)create mode 100644
drivers/gpu/drm/xen/Kconfigcreate mode 100644drivers/gpu/drm/xen/Makefilecreate mode 100644drivers/gpu/drm/xen/xen_drm_front.cdrivers/gpu/drm/Kconfig +0
-0@@ -289,6 +289,8 @@ source "drivers/gpu/drm/pl111/Kconfig"source "
drivers/gpu/drm/tve200/Kconfig"
+source "drivers/gpu/drm/xen/Kconfig"
+
# Keep legacy drivers last
menuconfigDRM_LEGACYdrivers/gpu/drm/Makefile +0
-0@@ -103,3 +103,4 @@ obj-$(CONFIG_DRM_MXSFB) += mxsfb/obj-$(CONFIG_DRM_TINYDRM) += tinydrm/
obj-$(CONFIG_DRM_PL111) += pl111/
obj-$(CONFIG_DRM_TVE200) += tve200/drivers/gpu/drm/Makefile +1
-0+obj-$(CONFIG_DRM_XEN) += xen/drivers/gpu/drm/xen/Kconfig new file +17
-0@@ -0,0 +1,17 @@ +config DRM_XEN + bool "DRM Support for Xen guest OS" + depends on XEN + help + Choose this option if you want to enable DRM support + for Xen. + +config DRM_XEN_FRONTEND + tristate "Para-virtualized frontend driver for Xen guest OS" + depends on DRM_XEN + depends on DRM + select DRM_KMS_HELPER + select VIDEOMODE_HELPERS + select XEN_XENBUS_FRONTEND + help + Choose this option if you want to enable a para-virtualized + frontend DRM/KMS driver for Xen guest OSes.drivers/gpu/drm/xen/Makefile new file +5
-0@@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 + +drm_xen_front-objs := xen_drm_front.o + +obj-$(CONFIG_DRM_XEN_FRONTEND) += drm_xen_front.odrivers/gpu/drm/xen/xen_drm_front.c new file +4
-0@@ -0,0 +1,83 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License asQuoted 8 lines
published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.Use SPDX identifier instead (same applies for all other new sources):
Quoted 1 line
// SPDX-License-Identifier: GPL-2.0
Will update, thank you
Quoted 46 lines
Quoted 46 lines
+ *
+ * Copyright (C) 2016-2018 EPAM Systems Inc.
+ *
+ * Author: Oleksandr Andrushchenko <[email protected]>
+ */drivers/gpu/drm/xen/xen_drm_front.c new file +41
-0+ +#include <drm/drmP.h> + +#include <xen/platform_pci.h> +#include <xen/xen.h> +#include <xen/xenbus.h> + +#include <xen/interface/io/displif.h> + +static void backend_on_changed (struct xenbus_device *xb_dev, + enum xenbus_state backend_state) +{ +} + +static int xen_drv_probe (struct xenbus_device *xb_dev, + const struct xenbus_device_id *id) +{ + return 0; +} + +static int xen_drv_remove (struct xenbus_device *dev) +{ + return 0; +} + +static const struct xenbus_device_id xen_drv_ids[] = { + { XENDISPL_DRIVER_NAME }, + { "" } +}; + +static struct xenbus_driver xen_driver = { + .ids = xen_drv_ids, + .probe = xen_drv_probe, + .remove = xen_drv_remove, + .otherend_changed = backend_on_changed, +}; + +static int __init xen_drv_init (void ) +{ + if (!xen_domain()) + return -ENODEV;Quoted 8 lines
Quoted 6 lines
+
+ if (xen_initial_domain()) {
+DRM_ERROR(XENDISPL_DRIVER_NAME " cannot run in initial domain\n");
+ return-ENODEV;
+ }Why not? Wouldn't that be possible in case of the backend living in a driver domain?
Quoted 4 lines
It is possible (and in my use-case backend indeed runs in a driver domain). I was just not sure if it is really a good idea to allow that. If you think this is ok, then I'll remove this check
I don't think the driver should decide that. This would be the job of Xen tools IMO.
Juergen
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Re: [PATCH 1/9] drm/xen-front: Introduce Xen para-virtualized frontend driver
Quoted 156 lines · Juergen Gross
Quoted 155 lines · Oleksandr Andrushchenko
Quoted 98 lines · Juergen Gross
Quoted 86 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Introduce skeleton of the para-virtualized Xen display frontend driver. This patch only adds required essential stubs.
Signed-off-by: Oleksandr Andrushchenko
<[email protected]>--- drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/xen/Kconfig | 17 ++++++++ drivers/gpu/drm/xen/Makefile | 5 +++ drivers/gpu/drm/xen/xen_drm_front.c | 83 +++++++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+)create mode 100644
drivers/gpu/drm/xen/Kconfigcreate mode 100644drivers/gpu/drm/xen/Makefilecreate mode 100644drivers/gpu/drm/xen/xen_drm_front.cdrivers/gpu/drm/Kconfig +1
-0@@ -289,6 +289,8 @@ source "drivers/gpu/drm/pl111/Kconfig" source "drivers/gpu/drm/tve200/Kconfig" +source "drivers/gpu/drm/xen/Kconfig" + # Keep legacy drivers last menuconfig DRM_LEGACYdrivers/gpu/drm/Makefile +1
-0@@ -103,3 +103,4 @@ obj-$(CONFIG_DRM_MXSFB) += mxsfb/ obj-$(CONFIG_DRM_TINYDRM) += tinydrm/ obj-$(CONFIG_DRM_PL111) += pl111/ obj-$(CONFIG_DRM_TVE200) += tve200/ +obj-$(CONFIG_DRM_XEN) += xen/drivers/gpu/drm/xen/Kconfig new file +17
-0@@ -0,0 +1,17 @@ +config DRM_XEN + bool "DRM Support for Xen guest OS" + depends on XEN + help + Choose this option if you want to enable DRM support + for Xen. + +config DRM_XEN_FRONTEND + tristate "Para-virtualized frontend driver for Xen guest OS" + depends on DRM_XEN + depends on DRM + select DRM_KMS_HELPER + select VIDEOMODE_HELPERS + select XEN_XENBUS_FRONTEND + help + Choose this option if you want to enable a para-virtualized + frontend DRM/KMS driver for Xen guest OSes.drivers/gpu/drm/xen/Makefile new file +5
-0@@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 + +drm_xen_front-objs := xen_drm_front.o + +obj-$(CONFIG_DRM_XEN_FRONTEND) += drm_xen_front.odrivers/gpu/drm/xen/xen_drm_front.c new file +4
-0@@ -0,0 +1,83 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License asQuoted 8 lines
published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.Use SPDX identifier instead (same applies for all other new sources):
Quoted 1 line
// SPDX-License-Identifier: GPL-2.0
Will update, thank you
Quoted 54 lines
Quoted 49 lines
+ *
+ * Copyright (C) 2016-2018 EPAM Systems Inc.
+ *
+ * Author: Oleksandr Andrushchenko <[email protected]>
+ */drivers/gpu/drm/xen/xen_drm_front.c new file +44
-0+ +#include <drm/drmP.h> + +#include <xen/platform_pci.h> +#include <xen/xen.h> +#include <xen/xenbus.h> + +#include <xen/interface/io/displif.h> + +static void backend_on_changed (struct xenbus_device *xb_dev, + enum xenbus_state backend_state) +{ +} + +static int xen_drv_probe (struct xenbus_device *xb_dev, + const struct xenbus_device_id *id) +{ + return 0; +} + +static int xen_drv_remove (struct xenbus_device *dev) +{ + return 0; +} + +static const struct xenbus_device_id xen_drv_ids[] = { + { XENDISPL_DRIVER_NAME }, + { "" } +}; + +static struct xenbus_driver xen_driver = { + .ids = xen_drv_ids, + .probe = xen_drv_probe, + .remove = xen_drv_remove, + .otherend_changed = backend_on_changed, +}; + +static int __init xen_drv_init(void) +{ + if (!xen_domain()) + return -ENODEV; + + if (xen_initial_domain()) { + DRM_ERROR(XENDISPL_DRIVER_NAME " cannot run in initialQuoted 3 lines
domain\n");
+ return-ENODEV;
+ }Why not? Wouldn't that be possible in case of the backend living in a driver domain?
Quoted 6 lines
Quoted 4 lines
It is possible (and in my use-case backend indeed runs in a driver domain). I was just not sure if it is really a good idea to allow that. If you think this is ok, then I'll remove this check
I don't think the driver should decide that. This would be the job of Xen tools IMO.
Agree, will remove
Quoted 2 lines
Juergen
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/9] drm/xen-front: Introduce Xen para-virtualized frontend driver
In reply to Juergen GrossQuoted 156 lines · Juergen Gross
Quoted 155 lines · Oleksandr Andrushchenko
Quoted 98 lines · Juergen Gross
Quoted 86 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Introduce skeleton of the para-virtualized Xen display frontend driver. This patch only adds required essential stubs.
Signed-off-by: Oleksandr Andrushchenko
<[email protected]>--- drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/xen/Kconfig | 17 ++++++++ drivers/gpu/drm/xen/Makefile | 5 +++ drivers/gpu/drm/xen/xen_drm_front.c | 83 +++++++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+)create mode 100644
drivers/gpu/drm/xen/Kconfigcreate mode 100644drivers/gpu/drm/xen/Makefilecreate mode 100644drivers/gpu/drm/xen/xen_drm_front.cdrivers/gpu/drm/Kconfig +1
-0@@ -289,6 +289,8 @@ source "drivers/gpu/drm/pl111/Kconfig" source "drivers/gpu/drm/tve200/Kconfig" +source "drivers/gpu/drm/xen/Kconfig" + # Keep legacy drivers last menuconfig DRM_LEGACYdrivers/gpu/drm/Makefile +1
-0@@ -103,3 +103,4 @@ obj-$(CONFIG_DRM_MXSFB) += mxsfb/ obj-$(CONFIG_DRM_TINYDRM) += tinydrm/ obj-$(CONFIG_DRM_PL111) += pl111/ obj-$(CONFIG_DRM_TVE200) += tve200/ +obj-$(CONFIG_DRM_XEN) += xen/drivers/gpu/drm/xen/Kconfig new file +17
-0@@ -0,0 +1,17 @@ +config DRM_XEN + bool "DRM Support for Xen guest OS" + depends on XEN + help + Choose this option if you want to enable DRM support + for Xen. + +config DRM_XEN_FRONTEND + tristate "Para-virtualized frontend driver for Xen guest OS" + depends on DRM_XEN + depends on DRM + select DRM_KMS_HELPER + select VIDEOMODE_HELPERS + select XEN_XENBUS_FRONTEND + help + Choose this option if you want to enable a para-virtualized + frontend DRM/KMS driver for Xen guest OSes.drivers/gpu/drm/xen/Makefile new file +5
-0@@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 + +drm_xen_front-objs := xen_drm_front.o + +obj-$(CONFIG_DRM_XEN_FRONTEND) += drm_xen_front.odrivers/gpu/drm/xen/xen_drm_front.c new file +4
-0@@ -0,0 +1,83 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License asQuoted 8 lines
published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.Use SPDX identifier instead (same applies for all other new sources):
Quoted 1 line
// SPDX-License-Identifier: GPL-2.0
Will update, thank you
Quoted 54 lines
Quoted 49 lines
+ *
+ * Copyright (C) 2016-2018 EPAM Systems Inc.
+ *
+ * Author: Oleksandr Andrushchenko <[email protected]>
+ */drivers/gpu/drm/xen/xen_drm_front.c new file +44
-0+ +#include <drm/drmP.h> + +#include <xen/platform_pci.h> +#include <xen/xen.h> +#include <xen/xenbus.h> + +#include <xen/interface/io/displif.h> + +static void backend_on_changed (struct xenbus_device *xb_dev, + enum xenbus_state backend_state) +{ +} + +static int xen_drv_probe (struct xenbus_device *xb_dev, + const struct xenbus_device_id *id) +{ + return 0; +} + +static int xen_drv_remove (struct xenbus_device *dev) +{ + return 0; +} + +static const struct xenbus_device_id xen_drv_ids[] = { + { XENDISPL_DRIVER_NAME }, + { "" } +}; + +static struct xenbus_driver xen_driver = { + .ids = xen_drv_ids, + .probe = xen_drv_probe, + .remove = xen_drv_remove, + .otherend_changed = backend_on_changed, +}; + +static int __init xen_drv_init(void) +{ + if (!xen_domain()) + return -ENODEV; + + if (xen_initial_domain()) { + DRM_ERROR(XENDISPL_DRIVER_NAME " cannot run in initialQuoted 3 lines
domain\n");
+ return-ENODEV;
+ }Why not? Wouldn't that be possible in case of the backend living in a driver domain?
Quoted 6 lines
Quoted 4 lines
It is possible (and in my use-case backend indeed runs in a driver domain). I was just not sure if it is really a good idea to allow that. If you think this is ok, then I'll remove this check
I don't think the driver should decide that. This would be the job of Xen tools IMO.
Agree, will remove
Quoted 2 lines
Juergen
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Re: [PATCH 1/9] drm/xen-front: Introduce Xen para-virtualized frontend driver
In reply to Juergen GrossQuoted 96 lines · Juergen Gross
Quoted 82 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Introduce skeleton of the para-virtualized Xen display frontend driver. This patch only adds required essential stubs.
Signed-off-by Oleksandr Andrushchenko <[email protected]>--- drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/xen/Kconfig | 17 ++++++++ drivers/gpu/drm/xen/Makefile | 5 +++ drivers/gpu/drm/xen/xen_drm_front.c | 83 +++++++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+)create mode 100644
drivers/gpu/drm/xen/Kconfigcreate mode 100644drivers/gpu/drm/xen/Makefilecreate mode 100644drivers/gpu/drm/xen/xen_drm_front.cdrivers/gpu/drm/Kconfig +2
-0@@ -289,6 +289,8 @@ source "drivers/gpu/drm/pl111/Kconfig" source "drivers/gpu/drm/tve200/Kconfig" +source "drivers/gpu/drm/xen/Kconfig" + # Keep legacy drivers last menuconfig DRM_LEGACYdrivers/gpu/drm/Makefile +1
-0@@ -103,3 +103,4 @@ obj-$(CONFIG_DRM_MXSFB) += mxsfb/ obj-$(CONFIG_DRM_TINYDRM) += tinydrm/ obj-$(CONFIG_DRM_PL111) += pl111/ obj-$(CONFIG_DRM_TVE200) += tve200/ +obj-$(CONFIG_DRM_XEN) += xen/drivers/gpu/drm/xen/Kconfig new file +17
-0@@ -0,0 +1,17 @@ +config DRM_XEN + bool "DRM Support for Xen guest OS" + depends on XEN + help + Choose this option if you want to enable DRM support + for Xen. + +config DRM_XEN_FRONTEND + tristate "Para-virtualized frontend driver for Xen guest OS" + depends on DRM_XEN + depends on DRM + select DRM_KMS_HELPER + select VIDEOMODE_HELPERS + select XEN_XENBUS_FRONTEND + help + Choose this option if you want to enable a para-virtualized + frontend DRM/KMS driver for Xen guest OSes.drivers/gpu/drm/xen/Makefile new file +5
-0@@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 + +drm_xen_front-objs := xen_drm_front.o + +obj-$(CONFIG_DRM_XEN_FRONTEND) += drm_xen_front.odrivers/gpu/drm/xen/xen_drm_front.c new file +2
-0@@ -0,0 +1,83 @@ +/* +* Xen para-virtual DRM device drivers/gpu/drm/xen/xen_drm_front.c line 12
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front.c new file +10
-0+* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. Use SPDX identifier instead (same applies for all other new sources):
Quoted 1 line
// SPDX-License-Identifier: GPL-2.0
Will update, thank you
Quoted 45 lines
Quoted 45 lines
drivers/gpu/drm/xen/xen_drm_front.c new file +45
-0+* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include <drm/drmP.h> + +#include <xen/platform_pci.h> +#include <xen/xen.h> +#include <xen/xenbus.h> + +#include <xen/interface/io/displif.h> + +static void backend_on_changed (struct xenbus_device *xb_dev, +enum xenbus_state backend_state) +{ +} + +static int xen_drv_probe (struct xenbus_device *xb_dev, +const struct xenbus_device_id *id) +{ +return 0 ; +} + +static int xen_drv_remove (struct xenbus_device *dev) +{ +return 0 ; +} + +static const struct xenbus_device_id xen_drv_ids[] = { + {XENDISPL_DRIVER_NAME }, + {"" } +}; + +static struct xenbus_driver xen_driver = { + .ids = xen_drv_ids, + .probe = xen_drv_probe, + .remove = xen_drv_remove, + .otherend_changed = backend_on_changed, +}; + +static int __init xen_drv_init (void ) +{ +if (!xen_domain ())
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front.c line 63
Quoted 6 lines
drivers/gpu/drm/xen/xen_drm_front.c new file +6
-0+return -ENODEV ; + +if (xen_initial_domain ()) { +DRM_ERROR (XENDISPL_DRIVER_NAME " cannot run in initial domain\n" ); +return -ENODEV ; + }Why not? Wouldn't that be possible in case of the backend living in a driver domain?
It is possible (and in my use-case backend indeed runs in a driver domain). I was just not sure if it is really a good idea to allow that. If you think this is ok, then I'll remove this check
Quoted 2 lines
Juergen
Thank you,
Oleksandr
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Re: [Xen-devel] [PATCH 1/9] drm/xen-front: Introduce Xen para-virtualized frontend driver
In reply to Oleksandr AndrushchenkoQuoted 82 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Introduce skeleton of the para-virtualized Xen display frontend driver. This patch only adds required essential stubs.
Signed-off-by Oleksandr Andrushchenko <[email protected]>--- drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/xen/Kconfig | 17 ++++++++ drivers/gpu/drm/xen/Makefile | 5 +++ drivers/gpu/drm/xen/xen_drm_front.c | 83 +++++++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+) create mode 100644 drivers/gpu/drm/xen/Kconfig create mode 100644 drivers/gpu/drm/xen/Makefile create mode 100644 drivers/gpu/drm/xen/xen_drm_front.cdrivers/gpu/drm/Kconfig +2
-0@@ -289,6 +289,8 @@ source "drivers/gpu/drm/pl111/Kconfig" source "drivers/gpu/drm/tve200/Kconfig" +source "drivers/gpu/drm/xen/Kconfig" + # Keep legacy drivers last menuconfig DRM_LEGACYdrivers/gpu/drm/Makefile +1
-0@@ -103,3 +103,4 @@ obj-$(CONFIG_DRM_MXSFB) += mxsfb/ obj-$(CONFIG_DRM_TINYDRM) += tinydrm/ obj-$(CONFIG_DRM_PL111) += pl111/ obj-$(CONFIG_DRM_TVE200) += tve200/ +obj-$(CONFIG_DRM_XEN) += xen/drivers/gpu/drm/xen/Kconfig new file +17
-0@@ -0,0 +1,17 @@ +config DRM_XEN + bool "DRM Support for Xen guest OS" + depends on XEN + help + Choose this option if you want to enable DRM support + for Xen. + +config DRM_XEN_FRONTEND + tristate "Para-virtualized frontend driver for Xen guest OS" + depends on DRM_XEN + depends on DRM + select DRM_KMS_HELPER + select VIDEOMODE_HELPERS + select XEN_XENBUS_FRONTEND + help + Choose this option if you want to enable a para-virtualized + frontend DRM/KMS driver for Xen guest OSes.drivers/gpu/drm/xen/Makefile new file +5
-0@@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 + +drm_xen_front-objs := xen_drm_front.o + +obj-$(CONFIG_DRM_XEN_FRONTEND) += drm_xen_front.odrivers/gpu/drm/xen/xen_drm_front.c new file +2
-0@@ -0,0 +1,83 @@ +/* +* Xen para-virtual DRM device
drivers/gpu/drm/xen/xen_drm_front.c line 12
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front.c new file +10
-0+* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details.
Most Xen drivers in Linux use a dual GPL/BSD license, so that they can be imported into other non GPL OSes:
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation; or, when distributed separately from the Linux kernel or incorporated into other software packages, subject to the following license:
Permission is hereby granted, free of charge, to any person obtaining a copy of this source file (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
IMO it would be good to release this driver under the same license, so it can be incorporated into other OSes.
Thanks, Roger.
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Re: [Xen-devel] [PATCH 1/9] drm/xen-front: Introduce Xen para-virtualized frontend driver
Quoted 120 lines · Roger Pau Monné
Quoted 82 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Introduce skeleton of the para-virtualized Xen display frontend driver. This patch only adds required essential stubs.
Signed-off-by Oleksandr Andrushchenko <[email protected]>--- drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/xen/Kconfig | 17 ++++++++ drivers/gpu/drm/xen/Makefile | 5 +++ drivers/gpu/drm/xen/xen_drm_front.c | 83 +++++++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+)create mode 100644
drivers/gpu/drm/xen/Kconfigcreate mode 100644drivers/gpu/drm/xen/Makefilecreate mode 100644drivers/gpu/drm/xen/xen_drm_front.cdrivers/gpu/drm/Kconfig +2
-0@@ -289,6 +289,8 @@ source "drivers/gpu/drm/pl111/Kconfig" source "drivers/gpu/drm/tve200/Kconfig" +source "drivers/gpu/drm/xen/Kconfig" + # Keep legacy drivers last menuconfig DRM_LEGACYdrivers/gpu/drm/Makefile +1
-0@@ -103,3 +103,4 @@ obj-$(CONFIG_DRM_MXSFB) += mxsfb/ obj-$(CONFIG_DRM_TINYDRM) += tinydrm/ obj-$(CONFIG_DRM_PL111) += pl111/ obj-$(CONFIG_DRM_TVE200) += tve200/ +obj-$(CONFIG_DRM_XEN) += xen/drivers/gpu/drm/xen/Kconfig new file +17
-0@@ -0,0 +1,17 @@ +config DRM_XEN + bool "DRM Support for Xen guest OS" + depends on XEN + help + Choose this option if you want to enable DRM support + for Xen. + +config DRM_XEN_FRONTEND + tristate "Para-virtualized frontend driver for Xen guest OS" + depends on DRM_XEN + depends on DRM + select DRM_KMS_HELPER + select VIDEOMODE_HELPERS + select XEN_XENBUS_FRONTEND + help + Choose this option if you want to enable a para-virtualized + frontend DRM/KMS driver for Xen guest OSes.drivers/gpu/drm/xen/Makefile new file +5
-0@@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 + +drm_xen_front-objs := xen_drm_front.o + +obj-$(CONFIG_DRM_XEN_FRONTEND) += drm_xen_front.odrivers/gpu/drm/xen/xen_drm_front.c new file +2
-0@@ -0,0 +1,83 @@ +/* +* Xen para-virtual DRM device drivers/gpu/drm/xen/xen_drm_front.c line 12
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front.c new file +10
-0+* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. Most Xen drivers in Linux use a dual GPL/BSD license, so that they can be imported into other non GPL OSes:
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation; or, when distributed separately from the Linux kernel or incorporated into other software packages, subject to the following license:
Permission is hereby granted, free of charge, to any person obtaining a copy of this source file (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Quoted 2 lines
IMO it would be good to release this driver under the same license, so it can be incorporated into other OSes.
I am in any way expert in licensing, but the above seems to be /* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
At least this is what I see at [1] for MIT.
Could you please tell which license(s) as listed at [1] would be appropriate for Xen drivers in terms of how it is expected to appear in the kernel code, e.g. expected SPDX-License-Identifier?
Quoted 1 line
Thanks, Roger.
Thank you,
Oleksandr
[1] https://spdx.org/licenses/
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Xen-devel] [PATCH 1/9] drm/xen-front: Introduce Xen para-virtualized frontend driver
Quoted 46 lines · Oleksandr Andrushchenko
Quoted 43 lines · Roger Pau Monné
Quoted 5 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front.c new file +2
-0@@ -0,0 +1,83 @@ +/* +* Xen para-virtual DRM device drivers/gpu/drm/xen/xen_drm_front.c line 12
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front.c new file +10
-0+* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. Most Xen drivers in Linux use a dual GPL/BSD license, so that they can be imported into other non GPL OSes:
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation; or, when distributed separately from the Linux kernel or incorporated into other software packages, subject to the following license:
Permission is hereby granted, free of charge, to any person obtaining a copy of this source file (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Quoted 2 lines
IMO it would be good to release this driver under the same license, so it can be incorporated into other OSes.
Quoted 7 lines
I am in any way expert in licensing, but the above seems to be /* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
At least this is what I see at [1] for MIT.
Could you please tell which license(s) as listed at [1] would be appropriate for Xen drivers in terms of how it is expected to appear in the kernel code, e.g. expected SPDX-License-Identifier?
I would be fine with anything MIT/BSD-*/Apache-* like. In the Xen community we have generally done dual GPL-2.0 MIT, so your proposed tag looks fine IMO (I would also personally be fine with MIT/BSD-*/Apache-* only).
The point is that it would be good to have the code under a more permissive license so it can be integrated into non GPL OSes in the future if needed, and that your code could be used as a reference for that.
Thanks, Roger.
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Re: [Xen-devel] [PATCH 1/9] drm/xen-front: Introduce Xen para-virtualized frontend driver
Quoted 54 lines · Roger Pau Monné
Quoted 46 lines · Oleksandr Andrushchenko
Quoted 43 lines · Roger Pau Monné
Quoted 5 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front.c new file +2
-0@@ -0,0 +1,83 @@ +/* +* Xen para-virtual DRM device drivers/gpu/drm/xen/xen_drm_front.c line 12
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front.c new file +10
-0+* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. Most Xen drivers in Linux use a dual GPL/BSD license, so that they can be imported into other non GPL OSes:
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation; or, when distributed separately from the Linux kernel or incorporated into other software packages, subject to the following license:
Permission is hereby granted, free of charge, to any person obtaining a copy of this source file (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Quoted 2 lines
IMO it would be good to release this driver under the same license, so it can be incorporated into other OSes.
Quoted 7 lines
I am in any way expert in licensing, but the above seems to be /* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
At least this is what I see at [1] for MIT.
Could you please tell which license(s) as listed at [1] would be appropriate for Xen drivers in terms of how it is expected to appear in the kernel code, e.g. expected SPDX-License-Identifier?
Quoted 4 lines
I would be fine with anything MIT/BSD-*/Apache-* like. In the Xen community we have generally done dual GPL-2.0 MIT, so your proposed tag looks fine IMO (I would also personally be fine with MIT/BSD-*/Apache-* only).
Ok, then I am about to use /* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
Quoted 5 lines
The point is that it would be good to have the code under a more permissive license so it can be integrated into non GPL OSes in the future if needed, and that your code could be used as a reference for that.
That is clear, no objections
Quoted 1 line
Thanks, Roger.
Thank you,
Oleksandr
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/9] drm/xen-front: Introduce Xen para-virtualized frontend driver
In reply to Roger Pau MonnéQuoted 54 lines · Roger Pau Monné
Quoted 46 lines · Oleksandr Andrushchenko
Quoted 43 lines · Roger Pau Monné
Quoted 5 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front.c new file +2
-0@@ -0,0 +1,83 @@ +/* +* Xen para-virtual DRM device drivers/gpu/drm/xen/xen_drm_front.c line 12
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front.c new file +10
-0+* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. Most Xen drivers in Linux use a dual GPL/BSD license, so that they can be imported into other non GPL OSes:
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation; or, when distributed separately from the Linux kernel or incorporated into other software packages, subject to the following license:
Permission is hereby granted, free of charge, to any person obtaining a copy of this source file (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Quoted 2 lines
IMO it would be good to release this driver under the same license, so it can be incorporated into other OSes.
Quoted 7 lines
I am in any way expert in licensing, but the above seems to be /* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
At least this is what I see at [1] for MIT.
Could you please tell which license(s) as listed at [1] would be appropriate for Xen drivers in terms of how it is expected to appear in the kernel code, e.g. expected SPDX-License-Identifier?
Quoted 4 lines
I would be fine with anything MIT/BSD-*/Apache-* like. In the Xen community we have generally done dual GPL-2.0 MIT, so your proposed tag looks fine IMO (I would also personally be fine with MIT/BSD-*/Apache-* only).
Ok, then I am about to use /* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
Quoted 5 lines
The point is that it would be good to have the code under a more permissive license so it can be integrated into non GPL OSes in the future if needed, and that your code could be used as a reference for that.
That is clear, no objections
Quoted 1 line
Thanks, Roger.
Thank you,
Oleksandr
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Re: [PATCH 1/9] drm/xen-front: Introduce Xen para-virtualized frontend driver
In reply to Roger Pau MonnéQuoted 120 lines · Roger Pau Monné
Quoted 82 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Introduce skeleton of the para-virtualized Xen display frontend driver. This patch only adds required essential stubs.
Signed-off-by Oleksandr Andrushchenko <[email protected]>--- drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/xen/Kconfig | 17 ++++++++ drivers/gpu/drm/xen/Makefile | 5 +++ drivers/gpu/drm/xen/xen_drm_front.c | 83 +++++++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+)create mode 100644
drivers/gpu/drm/xen/Kconfigcreate mode 100644drivers/gpu/drm/xen/Makefilecreate mode 100644drivers/gpu/drm/xen/xen_drm_front.cdrivers/gpu/drm/Kconfig +2
-0@@ -289,6 +289,8 @@ source "drivers/gpu/drm/pl111/Kconfig" source "drivers/gpu/drm/tve200/Kconfig" +source "drivers/gpu/drm/xen/Kconfig" + # Keep legacy drivers last menuconfig DRM_LEGACYdrivers/gpu/drm/Makefile +1
-0@@ -103,3 +103,4 @@ obj-$(CONFIG_DRM_MXSFB) += mxsfb/ obj-$(CONFIG_DRM_TINYDRM) += tinydrm/ obj-$(CONFIG_DRM_PL111) += pl111/ obj-$(CONFIG_DRM_TVE200) += tve200/ +obj-$(CONFIG_DRM_XEN) += xen/drivers/gpu/drm/xen/Kconfig new file +17
-0@@ -0,0 +1,17 @@ +config DRM_XEN + bool "DRM Support for Xen guest OS" + depends on XEN + help + Choose this option if you want to enable DRM support + for Xen. + +config DRM_XEN_FRONTEND + tristate "Para-virtualized frontend driver for Xen guest OS" + depends on DRM_XEN + depends on DRM + select DRM_KMS_HELPER + select VIDEOMODE_HELPERS + select XEN_XENBUS_FRONTEND + help + Choose this option if you want to enable a para-virtualized + frontend DRM/KMS driver for Xen guest OSes.drivers/gpu/drm/xen/Makefile new file +5
-0@@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 + +drm_xen_front-objs := xen_drm_front.o + +obj-$(CONFIG_DRM_XEN_FRONTEND) += drm_xen_front.odrivers/gpu/drm/xen/xen_drm_front.c new file +2
-0@@ -0,0 +1,83 @@ +/* +* Xen para-virtual DRM device drivers/gpu/drm/xen/xen_drm_front.c line 12
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front.c new file +10
-0+* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. Most Xen drivers in Linux use a dual GPL/BSD license, so that they can be imported into other non GPL OSes:
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation; or, when distributed separately from the Linux kernel or incorporated into other software packages, subject to the following license:
Permission is hereby granted, free of charge, to any person obtaining a copy of this source file (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Quoted 2 lines
IMO it would be good to release this driver under the same license, so it can be incorporated into other OSes.
I am in any way expert in licensing, but the above seems to be /* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
At least this is what I see at [1] for MIT.
Could you please tell which license(s) as listed at [1] would be appropriate for Xen drivers in terms of how it is expected to appear in the kernel code, e.g. expected SPDX-License-Identifier?
Quoted 1 line
Thanks, Roger.
Thank you,
Oleksandr
[1] https://spdx.org/licenses/
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Re: [PATCH 1/9] drm/xen-front: Introduce Xen para-virtualized frontend driver
In reply to Oleksandr Andrushchenkodrivers/gpu/drm/xen/xen_drm_front.c line 52
Quoted 5 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front.c new file +5
-0+static struct xenbus_driver xen_driver = { + .ids = xen_drv_ids, + .probe = xen_drv_probe, + .remove = xen_drv_remove, + .otherend_changed = backend_on_changed,
What does "_on_" stand for?
-boris
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Re: [PATCH 1/9] drm/xen-front: Introduce Xen para-virtualized frontend driver
Quoted 7 lines · Boris Ostrovsky
drivers/gpu/drm/xen/xen_drm_front.c line 52
Quoted 5 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front.c new file +5
-0+static struct xenbus_driver xen_driver = { + .ids = xen_drv_ids, + .probe = xen_drv_probe, + .remove = xen_drv_remove, + .otherend_changed = backend_on_changed,What does "_on_" stand for?
Well, it is somewhat like a hint that this is called "on" event, e.g. event when the other end state has changed, backend in this case. It could be something like "backend_on_state_changed"
Quoted 1 line
-boris
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/9] drm/xen-front: Introduce Xen para-virtualized frontend driver
Quoted 11 lines · Oleksandr Andrushchenko
Quoted 7 lines · Boris Ostrovsky
drivers/gpu/drm/xen/xen_drm_front.c line 52
Quoted 5 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front.c new file +5
-0+static struct xenbus_driver xen_driver = { + .ids = xen_drv_ids, + .probe = xen_drv_probe, + .remove = xen_drv_remove, + .otherend_changed = backend_on_changed,What does "_on_" stand for?
Well, it is somewhat like a hint that this is called "on" event, e.g. event when the other end state has changed, backend in this case. It could be something like "
backend_on_state_changed"
If you look at other xenbus_drivers none of the uses this so I think we should stick to conventional naming. (and the same applies to other backend_on_* routines).
-boris
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Re: [PATCH 1/9] drm/xen-front: Introduce Xen para-virtualized frontend driver
Quoted 8 lines · Boris Ostrovsky
Quoted 7 lines · Oleksandr Andrushchenko
Quoted 6 lines · Boris Ostrovsky
Quoted 5 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front.c new file +5
-0+static struct xenbus_driver xen_driver = { + .ids = xen_drv_ids, + .probe = xen_drv_probe, + .remove = xen_drv_remove, + .otherend_changed = backend_on_changed,
Quoted 7 lines
Quoted 4 lines
Quoted 1 line
What does "_on_" stand for?
Well, it is somewhat like a hint that this is called "on" event, e.g. event when the other end state has changed, backend in this case. It could be something like "
backend_on_state_changed"If you look at other
xenbus_driversnone of the uses this so I think we should stick to conventional naming. (and the same applies to other backend_on_* routines).
ok, no problem. will rename to be aligned with other frontends
Quoted 2 lines
-boris
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/9] drm/xen-front: Introduce Xen para-virtualized frontend driver
In reply to Boris OstrovskyQuoted 8 lines · Boris Ostrovsky
Quoted 7 lines · Oleksandr Andrushchenko
Quoted 6 lines · Boris Ostrovsky
Quoted 5 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front.c new file +5
-0+static struct xenbus_driver xen_driver = { + .ids = xen_drv_ids, + .probe = xen_drv_probe, + .remove = xen_drv_remove, + .otherend_changed = backend_on_changed,
Quoted 7 lines
Quoted 4 lines
Quoted 1 line
What does "_on_" stand for?
Well, it is somewhat like a hint that this is called "on" event, e.g. event when the other end state has changed, backend in this case. It could be something like "
backend_on_state_changed"If you look at other
xenbus_driversnone of the uses this so I think we should stick to conventional naming. (and the same applies to other backend_on_* routines).
ok, no problem. will rename to be aligned with other frontends
Quoted 2 lines
-boris
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Re: [PATCH 1/9] drm/xen-front: Introduce Xen para-virtualized frontend driver
In reply to Boris OstrovskyQuoted 7 lines · Boris Ostrovsky
drivers/gpu/drm/xen/xen_drm_front.c line 52
Quoted 5 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front.c new file +5
-0+static struct xenbus_driver xen_driver = { + .ids = xen_drv_ids, + .probe = xen_drv_probe, + .remove = xen_drv_remove, + .otherend_changed = backend_on_changed,What does "_on_" stand for?
Well, it is somewhat like a hint that this is called "on" event, e.g. event when the other end state has changed, backend in this case. It could be something like "backend_on_state_changed"
Quoted 1 line
-boris
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
PATCH 1/9 drm/xen-front: Introduce Xen para-virtualized frontend driver
In reply to Oleksandr AndrushchenkoFrom: Oleksandr Andrushchenko <[email protected]>
Introduce skeleton of the para-virtualized Xen display frontend driver. This patch only adds required essential stubs.
--- drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/xen/Kconfig | 17 ++++++++ drivers/gpu/drm/xen/Makefile | 5 +++ drivers/gpu/drm/xen/xen_drm_front.c | 83 +++++++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+) create mode 100644 drivers/gpu/drm/xen/Kconfig create mode 100644 drivers/gpu/drm/xen/Makefile create mode 100644 drivers/gpu/drm/xen/xen_drm_front.c
drivers/gpu/drm/Kconfig +2 -0
@@ -289,6 +289,8 @@ source "drivers/gpu/drm/pl111/Kconfig" source "drivers/gpu/drm/tve200/Kconfig" +source "drivers/gpu/drm/xen/Kconfig" + # Keep legacy drivers last menuconfig DRM_LEGACY
drivers/gpu/drm/Makefile +1 -0
@@ -103,3 +103,4 @@ obj-$(CONFIG_DRM_MXSFB) += mxsfb/ obj-$(CONFIG_DRM_TINYDRM) += tinydrm/ obj-$(CONFIG_DRM_PL111) += pl111/ obj-$(CONFIG_DRM_TVE200) += tve200/ +obj-$(CONFIG_DRM_XEN) += xen/
drivers/gpu/drm/xen/Kconfig new file +17 -0
@@ -0,0 +1,17 @@ +config DRM_XEN + bool "DRM Support for Xen guest OS" + depends on XEN + help + Choose this option if you want to enable DRM support + for Xen. + +config DRM_XEN_FRONTEND + tristate "Para-virtualized frontend driver for Xen guest OS" + depends on DRM_XEN + depends on DRM + select DRM_KMS_HELPER + select VIDEOMODE_HELPERS + select XEN_XENBUS_FRONTEND + help + Choose this option if you want to enable a para-virtualized + frontend DRM/KMS driver for Xen guest OSes.
drivers/gpu/drm/xen/Makefile new file +5 -0
@@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 + +drm_xen_front-objs := xen_drm_front.o + +obj-$(CONFIG_DRM_XEN_FRONTEND) += drm_xen_front.o
drivers/gpu/drm/xen/xen_drm_front.c new file +83 -0
83 lines not on this page · raw message
Signature · 7 lines
2.7.4 _______________________________________________ Xen-devel mailing list [email protected] https://lists.xenproject.org/mailman/listinfo/xen-devel
PATCH 2/9 drm/xen-front: Implement Xen bus state handling
In reply to Oleksandr AndrushchenkoFrom: Oleksandr Andrushchenko <[email protected]>
Initial handling for Xen bus states: implement
Xen bus state machine for the frontend driver according to the state diagram and recovery flow from display para-virtualized
protocol: xen/interface/io/displif.h.
--- drivers/gpu/drm/xen/xen_drm_front.c | 124 +++++++++++++++++++++++++++++++++++- drivers/gpu/drm/xen/xen_drm_front.h | 26 ++++++++ 2 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/xen/xen_drm_front.h
drivers/gpu/drm/xen/xen_drm_front.c +123 -1
@@ -24,19 +24,141 @@#include <xen/interface/io/displif.h> +#include "xen_drm_front.h" + +static void xen_drv_remove_internal (struct xen_drm_front_info *front_info) +{ +} + +static int backend_on_initwait (struct xen_drm_front_info *front_info) +{ +return 0 ; +} + +static int backend_on_connected (struct xen_drm_front_info *front_info) +{ +return 0 ; +} + +static void backend_on_disconnected (struct xen_drm_front_info *front_info) +{ +xenbus_switch_state (front_info->xb_dev, XenbusStateInitialising); +} +static void backend_on_changed (struct xenbus_device *xb_dev,enum xenbus_state backend_state) { +struct xen_drm_front_info *front_info =dev_get_drvdata (&xb_dev->dev); +int ret; + +DRM_DEBUG ("Backend state is %s, front is %s\n" , +xenbus_strstate (backend_state), +xenbus_strstate (xb_dev->state)); + +switch (backend_state) { +case XenbusStateReconfiguring: +/* fall through */ +case XenbusStateReconfigured: +/* fall through */ +case XenbusStateInitialised: +break ; + +case XenbusStateInitialising: +/* recovering after backend unexpected closure */ +backend_on_disconnected (front_info); +break ; + +case XenbusStateInitWait: +/* recovering after backend unexpected closure */ +backend_on_disconnected (front_info); +if (xb_dev->state != XenbusStateInitialising) +break ; + + ret =backend_on_initwait (front_info); +if (ret <0 ) +xenbus_dev_fatal (xb_dev, ret,"initializing frontend" ); +else +xenbus_switch_state (xb_dev, XenbusStateInitialised); +break ; + +case XenbusStateConnected: +if (xb_dev->state != XenbusStateInitialised) +break ; + + ret =backend_on_connected (front_info); +if (ret <0 ) +xenbus_dev_fatal (xb_dev, ret,"initializing DRM driver" ); +else +xenbus_switch_state (xb_dev, XenbusStateConnected); +break ; + +case XenbusStateClosing: +/* +* in this state backend starts freeing resources, +* so let it go into closed state, so we can also +* remove ours +*/ +break ; + +case XenbusStateUnknown: +/* fall through */ +case XenbusStateClosed: +if (xb_dev->state == XenbusStateClosed) +break ; + +backend_on_disconnected (front_info); +break ; + } }static int xen_drv_probe (struct xenbus_device *xb_dev,const struct xenbus_device_id *id) { -return 0 ; +struct xen_drm_front_info *front_info; + + front_info =devm_kzalloc (&xb_dev->dev, +sizeof (*front_info),GFP_KERNEL ); +if (!front_info) { +xenbus_dev_fatal (xb_dev, -ENOMEM ,"allocating device memory" ); +return -ENOMEM ; + } + + front_info->xb_dev = xb_dev; +dev_set_drvdata (&xb_dev->dev, front_info); +return xenbus_switch_state (xb_dev, XenbusStateInitialising); }static int xen_drv_remove (struct xenbus_device *dev) { +struct xen_drm_front_info *front_info =dev_get_drvdata (&dev->dev); +int to =100 ; + +xenbus_switch_state (dev, XenbusStateClosing); + +/* +* On driver removal it is disconnected from XenBus, +* so no backend state change events come via .otherend_changed +* callback. This prevents us from exiting gracefully, e.g. +* signaling the backend to free event channels, waiting for its +* state to change to XenbusStateClosed and cleaning at our end. +* Normally when front driver removed backend will finally go into +* XenbusStateInitWait state. +* +* Workaround: read backend's state manually and wait with time-out. +*/ +while ((xenbus_read_unsigned (front_info->xb_dev->otherend, +"state" , XenbusStateUnknown) != XenbusStateInitWait) && + to--) +msleep (10 ); + +if (!to) +DRM_ERROR ("Backend state is %s while removing driver\n" , +xenbus_strstate (xenbus_read_unsigned ( + front_info->xb_dev->otherend, +"state" , XenbusStateUnknown))); + +xen_drv_remove_internal (front_info); +xenbus_frontend_closed (dev);return 0 ; }
drivers/gpu/drm/xen/xen_drm_front.h new file +26 -0
@@ -0,0 +1,26 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_H_ +#define __XEN_DRM_FRONT_H_ + +struct xen_drm_front_info { +struct xenbus_device *xb_dev; +}; + +#endif /* __XEN_DRM_FRONT_H_ */
Signature · 6 lines
2.7.4 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 2/9] drm/xen-front: Implement Xen bus state handling
Quoted 109 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Initial handling for Xen bus states: implement
Xen bus state machine for the frontend driver according to the state diagram and recovery flow from display para-virtualized
protocol:xen/interface/io/displif.h.Signed-off-by Oleksandr Andrushchenko <[email protected]>--- drivers/gpu/drm/xen/xen_drm_front.c | 124 +++++++++++++++++++++++++++++++++++- drivers/gpu/drm/xen/xen_drm_front.h | 26 ++++++++ 2 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/xen/xen_drm_front.hdrivers/gpu/drm/xen/xen_drm_front.c +82
-0@@ -24,19 +24,141 @@#include <xen/interface/io/displif.h> +#include "xen_drm_front.h" + +static void xen_drv_remove_internal (struct xen_drm_front_info *front_info) +{ +} + +static int backend_on_initwait (struct xen_drm_front_info *front_info) +{ +return 0 ; +} + +static int backend_on_connected (struct xen_drm_front_info *front_info) +{ +return 0 ; +} + +static void backend_on_disconnected (struct xen_drm_front_info *front_info) +{ +xenbus_switch_state (front_info->xb_dev, XenbusStateInitialising); +} +static void backend_on_changed (struct xenbus_device *xb_dev,enum xenbus_state backend_state) { +struct xen_drm_front_info *front_info =dev_get_drvdata (&xb_dev->dev); +int ret; + +DRM_DEBUG ("Backend state is %s, front is %s\n" , +xenbus_strstate (backend_state), +xenbus_strstate (xb_dev->state)); + +switch (backend_state) { +case XenbusStateReconfiguring: +/* fall through */ +case XenbusStateReconfigured: +/* fall through */ +case XenbusStateInitialised: +break ; + +case XenbusStateInitialising: +/* recovering after backend unexpected closure */ +backend_on_disconnected (front_info); +break ; + +case XenbusStateInitWait: +/* recovering after backend unexpected closure */ +backend_on_disconnected (front_info); +if (xb_dev->state != XenbusStateInitialising) +break ; + + ret =backend_on_initwait (front_info); +if (ret <0 ) +xenbus_dev_fatal (xb_dev, ret,"initializing frontend" ); +else +xenbus_switch_state (xb_dev, XenbusStateInitialised); +break ; + +case XenbusStateConnected: +if (xb_dev->state != XenbusStateInitialised) +break ; + + ret =backend_on_connected (front_info); +if (ret <0 ) +xenbus_dev_fatal (xb_dev, ret,"initializing DRM driver" ); +else +xenbus_switch_state (xb_dev, XenbusStateConnected); +break ; + +case XenbusStateClosing: +/* +* in this state backend starts freeing resources, +* so let it go into closed state, so we can also +* remove ours +*/ +break ; + +case XenbusStateUnknown: +/* fall through */ +case XenbusStateClosed: +if (xb_dev->state == XenbusStateClosed) +break ; + +backend_on_disconnected (front_info); +break ; + } }
drivers/gpu/drm/xen/xen_drm_front.c line 122
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front.c +6
-1static int xen_drv_probe (struct xenbus_device *xb_dev,const struct xenbus_device_id *id) { -return 0 ; +struct xen_drm_front_info *front_info; + + front_info =devm_kzalloc (&xb_dev->dev, +sizeof (*front_info),GFP_KERNEL ); +if (!front_info) { +xenbus_dev_fatal (xb_dev, -ENOMEM ,"allocating device memory" );
No need for message in case of allocation failure: this is handled in memory allocation already.
Juergen
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Oleksandr Andrushchenko
maintainerRe: [PATCH 2/9] drm/xen-front: Implement Xen bus state handling
Quoted 110 lines · Juergen Gross
Quoted 109 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Initial handling for Xen bus states: implement
Xen bus state machine for the frontend driver according to the state diagram and recovery flow from display para-virtualized
protocol:xen/interface/io/displif.h.Signed-off-by Oleksandr Andrushchenko <[email protected]>--- drivers/gpu/drm/xen/xen_drm_front.c | 124 +++++++++++++++++++++++++++++++++++- drivers/gpu/drm/xen/xen_drm_front.h | 26 ++++++++ 2 files changed, 149 insertions(+), 1 deletion(-)create mode 100644
drivers/gpu/drm/xen/xen_drm_front.hdrivers/gpu/drm/xen/xen_drm_front.c +82
-0@@ -24,19 +24,141 @@#include <xen/interface/io/displif.h> +#include "xen_drm_front.h" + +static void xen_drv_remove_internal (struct xen_drm_front_info *front_info) +{ +} + +static int backend_on_initwait (struct xen_drm_front_info *front_info) +{ +return 0 ; +} + +static int backend_on_connected (struct xen_drm_front_info *front_info) +{ +return 0 ; +} + +static void backend_on_disconnected (struct xen_drm_front_info *front_info) +{ +xenbus_switch_state (front_info->xb_dev, XenbusStateInitialising); +} +static void backend_on_changed (struct xenbus_device *xb_dev,enum xenbus_state backend_state) { +struct xen_drm_front_info *front_info =dev_get_drvdata (&xb_dev->dev); +int ret; + +DRM_DEBUG ("Backend state is %s, front is %s\n" , +xenbus_strstate (backend_state), +xenbus_strstate (xb_dev->state)); + +switch (backend_state) { +case XenbusStateReconfiguring: +/* fall through */ +case XenbusStateReconfigured: +/* fall through */ +case XenbusStateInitialised: +break ; + +case XenbusStateInitialising: +/* recovering after backend unexpected closure */ +backend_on_disconnected (front_info); +break ; + +case XenbusStateInitWait: +/* recovering after backend unexpected closure */ +backend_on_disconnected (front_info); +if (xb_dev->state != XenbusStateInitialising) +break ; + + ret =backend_on_initwait (front_info); +if (ret <0 ) +xenbus_dev_fatal (xb_dev, ret,"initializing frontend" ); +else +xenbus_switch_state (xb_dev, XenbusStateInitialised); +break ; + +case XenbusStateConnected: +if (xb_dev->state != XenbusStateInitialised) +break ; + + ret =backend_on_connected (front_info); +if (ret <0 ) +xenbus_dev_fatal (xb_dev, ret,"initializing DRM driver" ); +else +xenbus_switch_state (xb_dev, XenbusStateConnected); +break ; + +case XenbusStateClosing: +/* +* in this state backend starts freeing resources, +* so let it go into closed state, so we can also +* remove ours +*/ +break ; + +case XenbusStateUnknown: +/* fall through */ +case XenbusStateClosed: +if (xb_dev->state == XenbusStateClosed) +break ; + +backend_on_disconnected (front_info); +break ; + } }
Quoted 12 lines
drivers/gpu/drm/xen/xen_drm_front.c line 122
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front.c +6
-1static int xen_drv_probe (struct xenbus_device *xb_dev,const struct xenbus_device_id *id) { -return 0 ; +struct xen_drm_front_info *front_info; + + front_info =devm_kzalloc (&xb_dev->dev, +sizeof (*front_info),GFP_KERNEL ); +if (!front_info) { +xenbus_dev_fatal (xb_dev, -ENOMEM ,"allocating device memory" );No need for message in case of allocation failure: this is handled in memory allocation already.
Will remove, thank you
Quoted 2 lines
Juergen
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
PATCH 2/9 drm/xen-front: Implement Xen bus state handling
In reply to Oleksandr AndrushchenkoFrom: Oleksandr Andrushchenko <[email protected]>
Initial handling for Xen bus states: implement
Xen bus state machine for the frontend driver according to the state diagram and recovery flow from display para-virtualized
protocol: xen/interface/io/displif.h.
--- drivers/gpu/drm/xen/xen_drm_front.c | 124 +++++++++++++++++++++++++++++++++++- drivers/gpu/drm/xen/xen_drm_front.h | 26 ++++++++ 2 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/xen/xen_drm_front.h
drivers/gpu/drm/xen/xen_drm_front.c +123 -1
@@ -24,19 +24,141 @@#include <xen/interface/io/displif.h> +#include "xen_drm_front.h" + +static void xen_drv_remove_internal (struct xen_drm_front_info *front_info) +{ +} + +static int backend_on_initwait (struct xen_drm_front_info *front_info) +{ +return 0 ; +} + +static int backend_on_connected (struct xen_drm_front_info *front_info) +{ +return 0 ; +} + +static void backend_on_disconnected (struct xen_drm_front_info *front_info) +{ +xenbus_switch_state (front_info->xb_dev, XenbusStateInitialising); +} +static void backend_on_changed (struct xenbus_device *xb_dev,enum xenbus_state backend_state) { +struct xen_drm_front_info *front_info =dev_get_drvdata (&xb_dev->dev); +int ret; + +DRM_DEBUG ("Backend state is %s, front is %s\n" , +xenbus_strstate (backend_state), +xenbus_strstate (xb_dev->state)); + +switch (backend_state) { +case XenbusStateReconfiguring: +/* fall through */ +case XenbusStateReconfigured: +/* fall through */ +case XenbusStateInitialised: +break ; + +case XenbusStateInitialising: +/* recovering after backend unexpected closure */ +backend_on_disconnected (front_info); +break ; + +case XenbusStateInitWait: +/* recovering after backend unexpected closure */ +backend_on_disconnected (front_info); +if (xb_dev->state != XenbusStateInitialising) +break ; + + ret =backend_on_initwait (front_info); +if (ret <0 ) +xenbus_dev_fatal (xb_dev, ret,"initializing frontend" ); +else +xenbus_switch_state (xb_dev, XenbusStateInitialised); +break ; + +case XenbusStateConnected: +if (xb_dev->state != XenbusStateInitialised) +break ; + + ret =backend_on_connected (front_info); +if (ret <0 ) +xenbus_dev_fatal (xb_dev, ret,"initializing DRM driver" ); +else +xenbus_switch_state (xb_dev, XenbusStateConnected); +break ; + +case XenbusStateClosing: +/* +* in this state backend starts freeing resources, +* so let it go into closed state, so we can also +* remove ours +*/ +break ; + +case XenbusStateUnknown: +/* fall through */ +case XenbusStateClosed: +if (xb_dev->state == XenbusStateClosed) +break ; + +backend_on_disconnected (front_info); +break ; + } }static int xen_drv_probe (struct xenbus_device *xb_dev,const struct xenbus_device_id *id) { -return 0 ; +struct xen_drm_front_info *front_info; + + front_info =devm_kzalloc (&xb_dev->dev, +sizeof (*front_info),GFP_KERNEL ); +if (!front_info) { +xenbus_dev_fatal (xb_dev, -ENOMEM ,"allocating device memory" ); +return -ENOMEM ; + } + + front_info->xb_dev = xb_dev; +dev_set_drvdata (&xb_dev->dev, front_info); +return xenbus_switch_state (xb_dev, XenbusStateInitialising); }static int xen_drv_remove (struct xenbus_device *dev) { +struct xen_drm_front_info *front_info =dev_get_drvdata (&dev->dev); +int to =100 ; + +xenbus_switch_state (dev, XenbusStateClosing); + +/* +* On driver removal it is disconnected from XenBus, +* so no backend state change events come via .otherend_changed +* callback. This prevents us from exiting gracefully, e.g. +* signaling the backend to free event channels, waiting for its +* state to change to XenbusStateClosed and cleaning at our end. +* Normally when front driver removed backend will finally go into +* XenbusStateInitWait state. +* +* Workaround: read backend's state manually and wait with time-out. +*/ +while ((xenbus_read_unsigned (front_info->xb_dev->otherend, +"state" , XenbusStateUnknown) != XenbusStateInitWait) && + to--) +msleep (10 ); + +if (!to) +DRM_ERROR ("Backend state is %s while removing driver\n" , +xenbus_strstate (xenbus_read_unsigned ( + front_info->xb_dev->otherend, +"state" , XenbusStateUnknown))); + +xen_drv_remove_internal (front_info); +xenbus_frontend_closed (dev);return 0 ; }
drivers/gpu/drm/xen/xen_drm_front.h new file +26 -0
@@ -0,0 +1,26 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_H_ +#define __XEN_DRM_FRONT_H_ + +struct xen_drm_front_info { +struct xenbus_device *xb_dev; +}; + +#endif /* __XEN_DRM_FRONT_H_ */
Signature · 7 lines
2.7.4 _______________________________________________ Xen-devel mailing list [email protected] https://lists.xenproject.org/mailman/listinfo/xen-devel
PATCH 3/9 drm/xen-front: Read driver configuration from Xen store
In reply to Oleksandr AndrushchenkoFrom: Oleksandr Andrushchenko <[email protected]>
Read configuration values from Xen store according to xen/interface/io/displif.h protocol:
- read connector(s) configuration
- read buffer allocation mode (backend/frontend)
--- drivers/gpu/drm/xen/Makefile | 3 +- drivers/gpu/drm/xen/xen_drm_front.c | 9 ++++ drivers/gpu/drm/xen/xen_drm_front.h | 3 ++ drivers/gpu/drm/xen/xen_drm_front_cfg.c | 84 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_cfg.h | 45 ++++++++++++++++++ 5 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/xen/xen_drm_front_cfg.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_cfg.h
drivers/gpu/drm/xen/Makefile +2 -1
@@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 -drm_xen_front-objs := xen_drm_front.o +drm_xen_front-objs := xen_drm_front.o \ + xen_drm_front_cfg.o obj-$(CONFIG_DRM_XEN_FRONTEND) += drm_xen_front.o
drivers/gpu/drm/xen/xen_drm_front.c +9 -0
@@ -32,6 +32,15 @@ static void xen_drv_remove_internal(struct xen_drm_front_info *front_info)static int backend_on_initwait (struct xen_drm_front_info *front_info) { +struct xen_drm_front_cfg *cfg = &front_info->cfg; +int ret; + + cfg->front_info = front_info; + ret =xen_drm_front_cfg_card (front_info, cfg); +if (ret <0 ) +return ret; + +DRM_INFO ("Have %d conector(s)\n" , cfg->num_connectors);return 0 ; }
drivers/gpu/drm/xen/xen_drm_front.h +3 -0
@@ -19,8 +19,11 @@#ifndef __XEN_DRM_FRONT_H_#define __XEN_DRM_FRONT_H_ +#include "xen_drm_front_cfg.h" +struct xen_drm_front_info {struct xenbus_device *xb_dev; +struct xen_drm_front_cfg cfg; };#endif /* __XEN_DRM_FRONT_H_ */
drivers/gpu/drm/xen/xen_drm_front_cfg.c new file +84 -0
84 lines not on this page · raw message
drivers/gpu/drm/xen/xen_drm_front_cfg.h new file +45 -0
45 lines not on this page · raw message
Signature · 6 lines
2.7.4 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 3/9] drm/xen-front: Read driver configuration from Xen store
Quoted 9 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front_cfg.c new file +9
-0+ +static int cfg_connector (struct xen_drm_front_info *front_info, +struct xen_drm_front_cfg_connector *connector, +const char *path,int index) +{ +char *connector_path; + + connector_path =devm_kasprintf (&front_info->xb_dev->dev, +GFP_KERNEL ,"%s/%d" , path, index);
drivers/gpu/drm/xen/xen_drm_front_cfg.c line 46
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front_cfg.c new file +10
-0+if (!connector_path) +return -ENOMEM ; + + connector->xenstore_path = connector_path; +if (xenbus_scanf (XBT_NIL , connector_path,XENDISPL_FIELD_RESOLUTION , +"%d" XENDISPL_RESOLUTION_SEPARATOR "%d" , + &connector->width, &connector->height) <0 ) { +/* either no entry configured or wrong resolution set */ + connector->width =0 ; + connector->height =0 ;
Do you also need to set connector->xenstore_path to NULL? Or maybe just set it after xenbus_scanf() call.
-boris
Re: [PATCH 3/9] drm/xen-front: Read driver configuration from Xen store
Quoted 14 lines · Boris Ostrovsky
Quoted 13 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front_cfg.c new file +13
-0+ +static int cfg_connector (struct xen_drm_front_info *front_info, +struct xen_drm_front_cfg_connector *connector, +const char *path,int index) +{ +char *connector_path; + + connector_path =devm_kasprintf (&front_info->xb_dev->dev, +GFP_KERNEL ,"%s/%d" , path, index); +if (!connector_path) +return -ENOMEM ; + + connector->xenstore_path = connector_path;
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_cfg.c line 46
Quoted 6 lines
drivers/gpu/drm/xen/xen_drm_front_cfg.c new file +6
-0+if (xenbus_scanf (XBT_NIL , connector_path,XENDISPL_FIELD_RESOLUTION , +"%d" XENDISPL_RESOLUTION_SEPARATOR "%d" , + &connector->width, &connector->height) <0 ) { +/* either no entry configured or wrong resolution set */ + connector->width =0 ; + connector->height =0 ;Do you also need to set
connector->xenstore_pathto NULL? Or maybe just set it afterxenbus_scanf()call.
Will move it down the code, after "if", thank you
Quoted 4 lines
-boris
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 3/9] drm/xen-front: Read driver configuration from Xen store
In reply to Boris OstrovskyQuoted 14 lines · Boris Ostrovsky
Quoted 13 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front_cfg.c new file +13
-0+ +static int cfg_connector (struct xen_drm_front_info *front_info, +struct xen_drm_front_cfg_connector *connector, +const char *path,int index) +{ +char *connector_path; + + connector_path =devm_kasprintf (&front_info->xb_dev->dev, +GFP_KERNEL ,"%s/%d" , path, index); +if (!connector_path) +return -ENOMEM ; + + connector->xenstore_path = connector_path;
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_cfg.c line 46
Quoted 6 lines
drivers/gpu/drm/xen/xen_drm_front_cfg.c new file +6
-0+if (xenbus_scanf (XBT_NIL , connector_path,XENDISPL_FIELD_RESOLUTION , +"%d" XENDISPL_RESOLUTION_SEPARATOR "%d" , + &connector->width, &connector->height) <0 ) { +/* either no entry configured or wrong resolution set */ + connector->width =0 ; + connector->height =0 ;Do you also need to set
connector->xenstore_pathto NULL? Or maybe just set it afterxenbus_scanf()call.
Will move it down the code, after "if", thank you
Quoted 4 lines
-boris
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
PATCH 3/9 drm/xen-front: Read driver configuration from Xen store
In reply to Oleksandr AndrushchenkoFrom: Oleksandr Andrushchenko <[email protected]>
Read configuration values from Xen store according to xen/interface/io/displif.h protocol:
- read connector(s) configuration
- read buffer allocation mode (backend/frontend)
--- drivers/gpu/drm/xen/Makefile | 3 +- drivers/gpu/drm/xen/xen_drm_front.c | 9 ++++ drivers/gpu/drm/xen/xen_drm_front.h | 3 ++ drivers/gpu/drm/xen/xen_drm_front_cfg.c | 84 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_cfg.h | 45 ++++++++++++++++++ 5 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/xen/xen_drm_front_cfg.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_cfg.h
drivers/gpu/drm/xen/Makefile +2 -1
@@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 -drm_xen_front-objs := xen_drm_front.o +drm_xen_front-objs := xen_drm_front.o \ + xen_drm_front_cfg.o obj-$(CONFIG_DRM_XEN_FRONTEND) += drm_xen_front.o
drivers/gpu/drm/xen/xen_drm_front.c +9 -0
@@ -32,6 +32,15 @@ static void xen_drv_remove_internal(struct xen_drm_front_info *front_info)static int backend_on_initwait (struct xen_drm_front_info *front_info) { +struct xen_drm_front_cfg *cfg = &front_info->cfg; +int ret; + + cfg->front_info = front_info; + ret =xen_drm_front_cfg_card (front_info, cfg); +if (ret <0 ) +return ret; + +DRM_INFO ("Have %d conector(s)\n" , cfg->num_connectors);return 0 ; }
drivers/gpu/drm/xen/xen_drm_front.h +3 -0
@@ -19,8 +19,11 @@#ifndef __XEN_DRM_FRONT_H_#define __XEN_DRM_FRONT_H_ +#include "xen_drm_front_cfg.h" +struct xen_drm_front_info {struct xenbus_device *xb_dev; +struct xen_drm_front_cfg cfg; };#endif /* __XEN_DRM_FRONT_H_ */
drivers/gpu/drm/xen/xen_drm_front_cfg.c new file +84 -0
84 lines not on this page · raw message
drivers/gpu/drm/xen/xen_drm_front_cfg.h new file +45 -0
45 lines not on this page · raw message
Signature · 7 lines
2.7.4 _______________________________________________ Xen-devel mailing list [email protected] https://lists.xenproject.org/mailman/listinfo/xen-devel
PATCH 4/9 drm/xen-front: Implement Xen event channel handling
In reply to Oleksandr AndrushchenkoFrom: Oleksandr Andrushchenko <[email protected]>
Handle Xen event channels:
- create for all configured connectors 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
--- drivers/gpu/drm/xen/Makefile | 1 + drivers/gpu/drm/xen/xen_drm_front.c | 16 +- drivers/gpu/drm/xen/xen_drm_front.h | 22 ++ drivers/gpu/drm/xen/xen_drm_front_evtchnl.c | 399 ++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_evtchnl.h | 89 +++++++ 5 files changed, 526 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/xen/xen_drm_front_evtchnl.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_evtchnl.h
drivers/gpu/drm/xen/Makefile +1 -0
@@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 drm_xen_front-objs := xen_drm_front.o \ + xen_drm_front_evtchnl.o \ xen_drm_front_cfg.o obj-$(CONFIG_DRM_XEN_FRONTEND) += drm_xen_front.o
drivers/gpu/drm/xen/xen_drm_front.c +15 -1
@@ -25,9 +25,15 @@#include <xen/interface/io/displif.h> #include "xen_drm_front.h" +#include "xen_drm_front_evtchnl.h" + +static struct xen_drm_front_ops front_ops = { +/* placeholder for now */ +};static void xen_drv_remove_internal (struct xen_drm_front_info *front_info) { +xen_drm_front_evtchnl_free_all (front_info); }static int backend_on_initwait (struct xen_drm_front_info *front_info)
@@ -41,16 +47,23 @@ static int backend_on_initwait(struct xen_drm_front_info *front_info)return ret;DRM_INFO ("Have %d conector(s)\n" , cfg->num_connectors); -return 0 ; +/* Create event channels for all connectors and publish */ + ret =xen_drm_front_evtchnl_create_all (front_info, &front_ops); +if (ret <0 ) +return ret; + +return xen_drm_front_evtchnl_publish_all (front_info); }static int backend_on_connected (struct xen_drm_front_info *front_info) { +xen_drm_front_evtchnl_set_state (front_info,EVTCHNL_STATE_CONNECTED );return 0 ; }static void backend_on_disconnected (struct xen_drm_front_info *front_info) { +xen_drm_front_evtchnl_set_state (front_info,EVTCHNL_STATE_DISCONNECTED );xenbus_switch_state (front_info->xb_dev, XenbusStateInitialising); }
@@ -133,6 +146,7 @@ static int xen_drv_probe(struct xenbus_device *xb_dev, } 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); }
drivers/gpu/drm/xen/xen_drm_front.h +22 -0
@@ -21,8 +21,30 @@#include "xen_drm_front_cfg.h" +#ifndef GRANT_INVALID_REF +/* +* Note on usage of grant reference 0 as invalid grant reference: +* grant reference 0 is valid, but never exposed to a PV driver, +* because of the fact it is already in use/reserved by the PV console. +*/ +#define GRANT_INVALID_REF 0 +#endif + +struct xen_drm_front_ops { +/* CAUTION! this is called with a spin_lock held! */ +void (*on_frame_done)(struct platform_device *pdev, +int conn_idx,uint64_t fb_cookie); +}; +struct xen_drm_front_info {struct xenbus_device *xb_dev; +/* to protect data between backend IO code and interrupt handler */ +spinlock_t io_lock; +/* virtual DRM platform device */ +struct platform_device *drm_pdev; + +int num_evt_pairs; +struct xen_drm_front_evtchnl_pair *evt_pairs;struct xen_drm_front_cfg cfg; };
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c new file +399 -0
399 lines not on this page · raw message
drivers/gpu/drm/xen/xen_drm_front_evtchnl.h new file +89 -0
89 lines not on this page · raw message
Signature · 6 lines
2.7.4 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 4/9] drm/xen-front: Implement Xen event channel handling
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c line 42
Quoted 13 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c new file +13
-0+ +static irqreturn_t evtchnl_interrupt_ctrl (int irq,void *dev_id) +{ +struct xen_drm_front_evtchnl *evtchnl = dev_id; +struct xen_drm_front_info *front_info = evtchnl->front_info; +struct xendispl_resp *resp; +RING_IDX i, rp; +unsigned long flags; + +spin_lock_irqsave (&front_info->io_lock, flags); + +if (unlikely (evtchnl->state !=EVTCHNL_STATE_CONNECTED )) + goto out;
Do you need to check the state under lock? (in other routines too).
...
Quoted 27 lines
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c new file +27
-0+ +static void evtchnl_free (struct xen_drm_front_info *front_info, +struct xen_drm_front_evtchnl *evtchnl) +{ +unsigned long page =0 ; + +if (evtchnl->type ==EVTCHNL_TYPE_REQ ) + page = (unsigned long )evtchnl->u.req.ring.sring; +else if (evtchnl->type ==EVTCHNL_TYPE_EVT ) + page = (unsigned long )evtchnl->u.evt.page; +if (!page) +return ; + + evtchnl->state =EVTCHNL_STATE_DISCONNECTED ; + +if (evtchnl->type ==EVTCHNL_TYPE_REQ ) { +/* release all who still waits for response if any */ + evtchnl->u.req.resp_status = -EIO ; +complete_all (&evtchnl->u.req.completion); + } + +if (evtchnl->irq) +unbind_from_irqhandler (evtchnl->irq, evtchnl); + +if (evtchnl->port) +xenbus_free_evtchn (front_info->xb_dev, evtchnl->port); +
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c line 166
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c new file +10
-0+/* end access and free the page */ +if (evtchnl->gref !=GRANT_INVALID_REF ) +gnttab_end_foreign_access (evtchnl->gref,0 , page); + +if (evtchnl->type ==EVTCHNL_TYPE_REQ ) + evtchnl->u.req.ring.sring =NULL ; +else + evtchnl->u.evt.page =NULL ; + +memset (evtchnl,0 ,sizeof (*evtchnl));
Since you are zeroing out the structure you don't need to set fields to zero.
I also think you need to free the page.
-boris
Re: [PATCH 4/9] drm/xen-front: Implement Xen event channel handling
Quoted 15 lines · Boris Ostrovsky
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c line 42
Quoted 13 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c new file +13
-0+ +static irqreturn_t evtchnl_interrupt_ctrl (int irq,void *dev_id) +{ +struct xen_drm_front_evtchnl *evtchnl = dev_id; +struct xen_drm_front_info *front_info = evtchnl->front_info; +struct xendispl_resp *resp; +RING_IDX i, rp; +unsigned long flags; + +spin_lock_irqsave (&front_info->io_lock, flags); + +if (unlikely (evtchnl->state !=EVTCHNL_STATE_CONNECTED )) + goto out;Do you need to check the state under lock? (in other routines too).
not really, will move out of the lock in interrupt handlers other places (I assume you refer to be_stream_do_io) it is set under lock as a part of atomic operation, e.g. we get a new request pointer from the ring and reset completion So, those places still seem to be ok
Quoted 33 lines
...
Quoted 31 lines
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c new file +31
-0+ +static void evtchnl_free (struct xen_drm_front_info *front_info, +struct xen_drm_front_evtchnl *evtchnl) +{ +unsigned long page =0 ; + +if (evtchnl->type ==EVTCHNL_TYPE_REQ ) + page = (unsigned long )evtchnl->u.req.ring.sring; +else if (evtchnl->type ==EVTCHNL_TYPE_EVT ) + page = (unsigned long )evtchnl->u.evt.page; +if (!page) +return ; + + evtchnl->state =EVTCHNL_STATE_DISCONNECTED ; + +if (evtchnl->type ==EVTCHNL_TYPE_REQ ) { +/* release all who still waits for response if any */ + evtchnl->u.req.resp_status = -EIO ; +complete_all (&evtchnl->u.req.completion); + } + +if (evtchnl->irq) +unbind_from_irqhandler (evtchnl->irq, evtchnl); + +if (evtchnl->port) +xenbus_free_evtchn (front_info->xb_dev, evtchnl->port); + +/* end access and free the page */ +if (evtchnl->gref !=GRANT_INVALID_REF ) +gnttab_end_foreign_access (evtchnl->gref,0 , page); +
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c line 166
Quoted 6 lines
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c new file +6
-0+if (evtchnl->type ==EVTCHNL_TYPE_REQ ) + evtchnl->u.req.ring.sring =NULL ; +else + evtchnl->u.evt.page =NULL ; + +memset (evtchnl,0 ,sizeof (*evtchnl));Since you are zeroing out the structure you don't need to set fields to zero.
good catch, thank you
Quoted 1 line
I also think you need to free the page.
it is freed by gnttab_end_foreign_access, please see [1]
Quoted 1 line
-boris
[1] https://elixir.bootlin.com/linux/v4.11-rc1/source/drivers/xen/grant-table.c#L380
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 4/9] drm/xen-front: Implement Xen event channel handling
Quoted 16 lines · Oleksandr Andrushchenko
Quoted 15 lines · Boris Ostrovsky
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c line 42
Quoted 13 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c new file +13
-0+ +static irqreturn_t evtchnl_interrupt_ctrl (int irq,void *dev_id) +{ +struct xen_drm_front_evtchnl *evtchnl = dev_id; +struct xen_drm_front_info *front_info = evtchnl->front_info; +struct xendispl_resp *resp; +RING_IDX i, rp; +unsigned long flags; + +spin_lock_irqsave (&front_info->io_lock, flags); + +if (unlikely (evtchnl->state !=EVTCHNL_STATE_CONNECTED )) + goto out;Do you need to check the state under lock? (in other routines too).
Quoted 2 lines
not really, will move out of the lock in interrupt handlers other places (I assume you refer to
be_stream_do_io)
I was mostly referring to evtchnl_interrupt_evt().
-boris
Quoted 3 lines
it is set under lock as a part of atomic operation, e.g. we get a new request pointer from the ring and reset completion So, those places still seem to be ok
Re: [PATCH 4/9] drm/xen-front: Implement Xen event channel handling
Quoted 17 lines · Boris Ostrovsky
Quoted 16 lines · Oleksandr Andrushchenko
Quoted 15 lines · Boris Ostrovsky
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c line 42
Quoted 13 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c new file +13
-0+ +static irqreturn_t evtchnl_interrupt_ctrl (int irq,void *dev_id) +{ +struct xen_drm_front_evtchnl *evtchnl = dev_id; +struct xen_drm_front_info *front_info = evtchnl->front_info; +struct xendispl_resp *resp; +RING_IDX i, rp; +unsigned long flags; + +spin_lock_irqsave (&front_info->io_lock, flags); + +if (unlikely (evtchnl->state !=EVTCHNL_STATE_CONNECTED )) + goto out;Do you need to check the state under lock? (in other routines too).
Quoted 4 lines
Quoted 2 lines
not really, will move out of the lock in interrupt handlers other places (I assume you refer to
be_stream_do_io)I was mostly referring to
evtchnl_interrupt_evt().
ah, then we are on the same page: I will move the check in interrupt handlers
Quoted 6 lines
-boris
Quoted 3 lines
it is set under lock as a part of atomic operation, e.g. we get a new request pointer from the ring and reset completion So, those places still seem to be ok
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 4/9] drm/xen-front: Implement Xen event channel handling
In reply to Boris OstrovskyQuoted 17 lines · Boris Ostrovsky
Quoted 16 lines · Oleksandr Andrushchenko
Quoted 15 lines · Boris Ostrovsky
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c line 42
Quoted 13 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c new file +13
-0+ +static irqreturn_t evtchnl_interrupt_ctrl (int irq,void *dev_id) +{ +struct xen_drm_front_evtchnl *evtchnl = dev_id; +struct xen_drm_front_info *front_info = evtchnl->front_info; +struct xendispl_resp *resp; +RING_IDX i, rp; +unsigned long flags; + +spin_lock_irqsave (&front_info->io_lock, flags); + +if (unlikely (evtchnl->state !=EVTCHNL_STATE_CONNECTED )) + goto out;Do you need to check the state under lock? (in other routines too).
Quoted 4 lines
Quoted 2 lines
not really, will move out of the lock in interrupt handlers other places (I assume you refer to
be_stream_do_io)I was mostly referring to
evtchnl_interrupt_evt().
ah, then we are on the same page: I will move the check in interrupt handlers
Quoted 6 lines
-boris
Quoted 3 lines
it is set under lock as a part of atomic operation, e.g. we get a new request pointer from the ring and reset completion So, those places still seem to be ok
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Re: [PATCH 4/9] drm/xen-front: Implement Xen event channel handling
In reply to Boris OstrovskyQuoted 15 lines · Boris Ostrovsky
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c line 42
Quoted 13 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c new file +13
-0+ +static irqreturn_t evtchnl_interrupt_ctrl (int irq,void *dev_id) +{ +struct xen_drm_front_evtchnl *evtchnl = dev_id; +struct xen_drm_front_info *front_info = evtchnl->front_info; +struct xendispl_resp *resp; +RING_IDX i, rp; +unsigned long flags; + +spin_lock_irqsave (&front_info->io_lock, flags); + +if (unlikely (evtchnl->state !=EVTCHNL_STATE_CONNECTED )) + goto out;Do you need to check the state under lock? (in other routines too).
not really, will move out of the lock in interrupt handlers other places (I assume you refer to be_stream_do_io) it is set under lock as a part of atomic operation, e.g. we get a new request pointer from the ring and reset completion So, those places still seem to be ok
Quoted 33 lines
...
Quoted 31 lines
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c new file +31
-0+ +static void evtchnl_free (struct xen_drm_front_info *front_info, +struct xen_drm_front_evtchnl *evtchnl) +{ +unsigned long page =0 ; + +if (evtchnl->type ==EVTCHNL_TYPE_REQ ) + page = (unsigned long )evtchnl->u.req.ring.sring; +else if (evtchnl->type ==EVTCHNL_TYPE_EVT ) + page = (unsigned long )evtchnl->u.evt.page; +if (!page) +return ; + + evtchnl->state =EVTCHNL_STATE_DISCONNECTED ; + +if (evtchnl->type ==EVTCHNL_TYPE_REQ ) { +/* release all who still waits for response if any */ + evtchnl->u.req.resp_status = -EIO ; +complete_all (&evtchnl->u.req.completion); + } + +if (evtchnl->irq) +unbind_from_irqhandler (evtchnl->irq, evtchnl); + +if (evtchnl->port) +xenbus_free_evtchn (front_info->xb_dev, evtchnl->port); + +/* end access and free the page */ +if (evtchnl->gref !=GRANT_INVALID_REF ) +gnttab_end_foreign_access (evtchnl->gref,0 , page); +
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c line 166
Quoted 6 lines
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c new file +6
-0+if (evtchnl->type ==EVTCHNL_TYPE_REQ ) + evtchnl->u.req.ring.sring =NULL ; +else + evtchnl->u.evt.page =NULL ; + +memset (evtchnl,0 ,sizeof (*evtchnl));Since you are zeroing out the structure you don't need to set fields to zero.
good catch, thank you
Quoted 1 line
I also think you need to free the page.
it is freed by gnttab_end_foreign_access, please see [1]
Quoted 1 line
-boris
[1] https://elixir.bootlin.com/linux/v4.11-rc1/source/drivers/xen/grant-table.c#L380
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
PATCH 4/9 drm/xen-front: Implement Xen event channel handling
In reply to Oleksandr AndrushchenkoFrom: Oleksandr Andrushchenko <[email protected]>
Handle Xen event channels:
- create for all configured connectors 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
--- drivers/gpu/drm/xen/Makefile | 1 + drivers/gpu/drm/xen/xen_drm_front.c | 16 +- drivers/gpu/drm/xen/xen_drm_front.h | 22 ++ drivers/gpu/drm/xen/xen_drm_front_evtchnl.c | 399 ++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_evtchnl.h | 89 +++++++ 5 files changed, 526 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/xen/xen_drm_front_evtchnl.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_evtchnl.h
drivers/gpu/drm/xen/Makefile +1 -0
@@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 drm_xen_front-objs := xen_drm_front.o \ + xen_drm_front_evtchnl.o \ xen_drm_front_cfg.o obj-$(CONFIG_DRM_XEN_FRONTEND) += drm_xen_front.o
drivers/gpu/drm/xen/xen_drm_front.c +15 -1
@@ -25,9 +25,15 @@#include <xen/interface/io/displif.h> #include "xen_drm_front.h" +#include "xen_drm_front_evtchnl.h" + +static struct xen_drm_front_ops front_ops = { +/* placeholder for now */ +};static void xen_drv_remove_internal (struct xen_drm_front_info *front_info) { +xen_drm_front_evtchnl_free_all (front_info); }static int backend_on_initwait (struct xen_drm_front_info *front_info)
@@ -41,16 +47,23 @@ static int backend_on_initwait(struct xen_drm_front_info *front_info)return ret;DRM_INFO ("Have %d conector(s)\n" , cfg->num_connectors); -return 0 ; +/* Create event channels for all connectors and publish */ + ret =xen_drm_front_evtchnl_create_all (front_info, &front_ops); +if (ret <0 ) +return ret; + +return xen_drm_front_evtchnl_publish_all (front_info); }static int backend_on_connected (struct xen_drm_front_info *front_info) { +xen_drm_front_evtchnl_set_state (front_info,EVTCHNL_STATE_CONNECTED );return 0 ; }static void backend_on_disconnected (struct xen_drm_front_info *front_info) { +xen_drm_front_evtchnl_set_state (front_info,EVTCHNL_STATE_DISCONNECTED );xenbus_switch_state (front_info->xb_dev, XenbusStateInitialising); }
@@ -133,6 +146,7 @@ static int xen_drv_probe(struct xenbus_device *xb_dev, } 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); }
drivers/gpu/drm/xen/xen_drm_front.h +22 -0
@@ -21,8 +21,30 @@#include "xen_drm_front_cfg.h" +#ifndef GRANT_INVALID_REF +/* +* Note on usage of grant reference 0 as invalid grant reference: +* grant reference 0 is valid, but never exposed to a PV driver, +* because of the fact it is already in use/reserved by the PV console. +*/ +#define GRANT_INVALID_REF 0 +#endif + +struct xen_drm_front_ops { +/* CAUTION! this is called with a spin_lock held! */ +void (*on_frame_done)(struct platform_device *pdev, +int conn_idx,uint64_t fb_cookie); +}; +struct xen_drm_front_info {struct xenbus_device *xb_dev; +/* to protect data between backend IO code and interrupt handler */ +spinlock_t io_lock; +/* virtual DRM platform device */ +struct platform_device *drm_pdev; + +int num_evt_pairs; +struct xen_drm_front_evtchnl_pair *evt_pairs;struct xen_drm_front_cfg cfg; };
drivers/gpu/drm/xen/xen_drm_front_evtchnl.c new file +399 -0
399 lines not on this page · raw message
drivers/gpu/drm/xen/xen_drm_front_evtchnl.h new file +89 -0
89 lines not on this page · raw message
Signature · 7 lines
2.7.4 _______________________________________________ Xen-devel mailing list [email protected] https://lists.xenproject.org/mailman/listinfo/xen-devel
PATCH 5/9 drm/xen-front: Implement handling of shared display buffers
In reply to Oleksandr AndrushchenkoFrom: Oleksandr Andrushchenko <[email protected]>
Implement shared buffer handling according to the para-virtualized display device protocol at xen/interface/io/displif.h:
- handle page directories according to displif protocol:
- allocate and share page directories
- grant references to the required set of pages for the page directory
- allocate xen balllooned pages via Xen balloon driver with alloc_xenballooned_pages/free_xenballooned_pages
- grant references to the required set of pages for the shared buffer itself
- implement pages map/unmap for the buffers allocated by the backend (gnttab_map_refs/gnttab_unmap_refs)
--- drivers/gpu/drm/xen/Makefile | 1 + drivers/gpu/drm/xen/xen_drm_front.c | 4 + drivers/gpu/drm/xen/xen_drm_front_shbuf.c | 430 ++++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_shbuf.h | 80 ++++++ 4 files changed, 515 insertions(+) create mode 100644 drivers/gpu/drm/xen/xen_drm_front_shbuf.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_shbuf.h
drivers/gpu/drm/xen/Makefile +1 -0
@@ -2,6 +2,7 @@ drm_xen_front-objs := xen_drm_front.o \ xen_drm_front_evtchnl.o \ + xen_drm_front_shbuf.o \ xen_drm_front_cfg.o obj-$(CONFIG_DRM_XEN_FRONTEND) += drm_xen_front.o
drivers/gpu/drm/xen/xen_drm_front.c +4 -0
@@ -26,6 +26,7 @@#include "xen_drm_front.h" #include "xen_drm_front_evtchnl.h" +#include "xen_drm_front_shbuf.h" static struct xen_drm_front_ops front_ops = {/* placeholder for now */
@@ -199,6 +200,9 @@ static struct xenbus_driver xen_driver = {static int __init xen_drv_init (void ) { +/* At the moment we only support case with XEN_PAGE_SIZE == PAGE_SIZE */ +BUILD_BUG_ON (XEN_PAGE_SIZE !=PAGE_SIZE ); +if (!xen_domain ())return -ENODEV ;
drivers/gpu/drm/xen/xen_drm_front_shbuf.c new file +430 -0
430 lines not on this page · raw message
drivers/gpu/drm/xen/xen_drm_front_shbuf.h new file +80 -0
80 lines not on this page · raw message
Signature · 6 lines
2.7.4 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 5/9] drm/xen-front: Implement handling of shared display buffers
drivers/gpu/drm/xen/xen_drm_front.c static struct xenbus_driver xen_driver = { · line 204
Quoted 5 lines · Oleksandr Andrushchenko
static int
__initxen_drv_init(void)
{drivers/gpu/drm/xen/xen_drm_front.c +2
-0+/* At the moment we only support case with XEN_PAGE_SIZE == PAGE_SIZE */ +BUILD_BUG_ON (XEN_PAGE_SIZE !=PAGE_SIZE );
Why BUILD_BUG_ON? This should simply not load if page sizes are different.
drivers/gpu/drm/xen/xen_drm_front_shbuf.c line 187
Quoted 2 lines
drivers/gpu/drm/xen/xen_drm_front_shbuf.c new file +2
-0+ ret =gnttab_map_refs (map_ops,NULL , buf->pages, buf->num_pages); +BUG_ON (ret);
We should try not to BUG*(). There are a few in this patch (and possibly others) that I think can be avoided.
Quoted 11 lines
drivers/gpu/drm/xen/xen_drm_front_shbuf.c new file +11
-0+ +static int alloc_storage (struct xen_drm_front_shbuf *buf) +{ +if (buf->sgt) { + buf->pages =kvmalloc_array (buf->num_pages, +sizeof (struct page *),GFP_KERNEL ); +if (!buf->pages) +return -ENOMEM ; + +if (drm_prime_sg_to_page_addr_arrays (buf->sgt, buf->pages, +NULL , buf->num_pages) <0 )
drivers/gpu/drm/xen/xen_drm_front_shbuf.c line 367
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front_shbuf.c new file +10
-0+return -EINVAL ; + } + + buf->grefs =kcalloc (buf->num_grefs,sizeof (*buf->grefs),GFP_KERNEL ); +if (!buf->grefs) +return -ENOMEM ; + + buf->directory =kcalloc (get_num_pages_dir (buf),PAGE_SIZE ,GFP_KERNEL ); +if (!buf->directory) +return -ENOMEM ;
You need to clean up on errors.
-boris
Quoted 3 lines
drivers/gpu/drm/xen/xen_drm_front_shbuf.c new file +3
-0+ +return 0 ; +}
Re: [PATCH 5/9] drm/xen-front: Implement handling of shared display buffers
Quoted 10 lines · Boris Ostrovsky
drivers/gpu/drm/xen/xen_drm_front.c static struct xenbus_driver xen_driver = { · line 204
Quoted 5 lines · Oleksandr Andrushchenko
static int __init xen_drv_init(void) {drivers/gpu/drm/xen/xen_drm_front.c +2
-0+/* At the moment we only support case with XEN_PAGE_SIZE == PAGE_SIZE */ +BUILD_BUG_ON (XEN_PAGE_SIZE !=PAGE_SIZE );Why
BUILD_BUG_ON? This should simply not load if page sizes are different.
This is a compile time check, so if kernel/Xen is configured to use page size combination which is not supported by the driver it will fail during compilation. This seems correct to me, because you shouldn't even try to load the driver which cannot handle different page sizes to not make any harm.
Quoted 9 lines
drivers/gpu/drm/xen/xen_drm_front_shbuf.c line 187
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front_shbuf.c new file +2
-0+ ret =gnttab_map_refs (map_ops,NULL , buf->pages, buf->num_pages); +BUG_ON (ret);We should try not to BUG*(). There are a few in this patch (and possibly others) that I think can be avoided.
I will rework BUG_* for map/unmap code to handle errors, but will still leave
/* either pages or sgt, not both */ BUG_ON(cfg->pages && cfg->sgt);
which is a real driver bug and must not happen
Quoted 17 lines
Quoted 17 lines
drivers/gpu/drm/xen/xen_drm_front_shbuf.c new file +14
-0+ +static int alloc_storage (struct xen_drm_front_shbuf *buf) +{ +if (buf->sgt) { + buf->pages =kvmalloc_array (buf->num_pages, +sizeof (struct page *),GFP_KERNEL ); +if (!buf->pages) +return -ENOMEM ; + +if (drm_prime_sg_to_page_addr_arrays (buf->sgt, buf->pages, +NULL , buf->num_pages) <0 ) +return -EINVAL ; + } +
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_shbuf.c line 367
Quoted 7 lines
drivers/gpu/drm/xen/xen_drm_front_shbuf.c new file +7
-0+ buf->grefs =kcalloc (buf->num_grefs,sizeof (*buf->grefs),GFP_KERNEL ); +if (!buf->grefs) +return -ENOMEM ; + + buf->directory =kcalloc (get_num_pages_dir (buf),PAGE_SIZE ,GFP_KERNEL ); +if (!buf->directory) +return -ENOMEM ;You need to clean up on errors.
this is called in xen_drm_front_shbuf_alloc and is properly cleaned on failure, e.g.:
ret = alloc_storage(buf);
if (ret)
goto fail;
[...]
fail:
xen_drm_front_shbuf_free(buf);
Quoted 5 lines
-boris
drivers/gpu/drm/xen/xen_drm_front_shbuf.c line 70
Quoted 3 lines
drivers/gpu/drm/xen/xen_drm_front_shbuf.c new file +3
-0+ +return 0 ; +}
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 5/9] drm/xen-front: Implement handling of shared display buffers
Quoted 12 lines · Oleksandr Andrushchenko
Quoted 11 lines · Boris Ostrovsky
Quoted 5 lines · Oleksandr Andrushchenko
static int
__initxen_drv_init(void)
{
+ /* At the moment we only support case withXEN_PAGE_SIZE==PAGE_SIZE*/
+BUILD_BUG_ON(XEN_PAGE_SIZE != PAGE_SIZE);Why
BUILD_BUG_ON? This should simply not load if page sizes are different.
Quoted 5 lines
This is a compile time check, so if kernel/Xen is configured to use page size combination which is not supported by the driver it will fail during compilation. This seems correct to me, because you shouldn't even try to load the driver which cannot handle different page sizes to not make any harm.
This will prevent whole kernel from building. So, for example, randconfig builds will fail.
Quoted 6 lines
Quoted 6 lines
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front_shbuf.c new file +2
-0+ ret =gnttab_map_refs (map_ops,NULL , buf->pages, buf->num_pages); +BUG_ON (ret);
Quoted 8 lines
Quoted 3 lines
We should try not to BUG*(). There are a few in this patch (and possibly others) that I think can be avoided.
I will rework BUG_* for map/unmap code to handle errors, but will still leave
/* either pages or sgt, not both */ BUG_ON(cfg->pages && cfg->sgt);which is a real driver bug and must not happen
Why not return an error?
In fact, AFAICS you only call it in patch 9 where both of these can be tested, in which case something like -EINVAL would look reasonable.
-boris
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Re: [PATCH 5/9] drm/xen-front: Implement handling of shared display buffers
Quoted 12 lines · Boris Ostrovsky
Quoted 11 lines · Oleksandr Andrushchenko
Quoted 10 lines · Boris Ostrovsky
Quoted 5 lines · Oleksandr Andrushchenko
static int
__initxen_drv_init(void)
{
+ /* At the moment we only support case withXEN_PAGE_SIZE==PAGE_SIZE*/
+BUILD_BUG_ON(XEN_PAGE_SIZE != PAGE_SIZE);Why
BUILD_BUG_ON? This should simply not load if page sizes are different.
Quoted 9 lines
Quoted 5 lines
This is a compile time check, so if kernel/Xen is configured to use page size combination which is not supported by the driver it will fail during compilation. This seems correct to me, because you shouldn't even try to load the driver which cannot handle different page sizes to not make any harm.
This will prevent whole kernel from building. So, for example, randconfig builds will fail.
makes a lot of sense, thank you
will rework so I reject to load if the requirement is not met
Quoted 12 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
drivers/gpu/drm/xen/xen_drm_front_shbuf.c new file +2
-0+ ret =gnttab_map_refs (map_ops,NULL , buf->pages, buf->num_pages); +BUG_ON (ret);Quoted 8 lines
Quoted 3 lines
We should try not to BUG*(). There are a few in this patch (and possibly others) that I think can be avoided.
I will rework BUG_* for map/unmap code to handle errors, but will still leave
/* either pages or sgt, not both */ BUG_ON(cfg->pages && cfg->sgt);which is a real driver bug and must not happen
Quoted 4 lines
Why not return an error?
In fact, AFAICS you only call it in patch 9 where both of these can be tested, in which case something like
-EINVALwould look reasonable.
ok, will remove BUG_ON as well
Quoted 1 line
-boris
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 5/9] drm/xen-front: Implement handling of shared display buffers
In reply to Boris OstrovskyQuoted 12 lines · Boris Ostrovsky
Quoted 11 lines · Oleksandr Andrushchenko
Quoted 10 lines · Boris Ostrovsky
Quoted 5 lines · Oleksandr Andrushchenko
static int
__initxen_drv_init(void)
{
+ /* At the moment we only support case withXEN_PAGE_SIZE==PAGE_SIZE*/
+BUILD_BUG_ON(XEN_PAGE_SIZE != PAGE_SIZE);Why
BUILD_BUG_ON? This should simply not load if page sizes are different.
Quoted 9 lines
Quoted 5 lines
This is a compile time check, so if kernel/Xen is configured to use page size combination which is not supported by the driver it will fail during compilation. This seems correct to me, because you shouldn't even try to load the driver which cannot handle different page sizes to not make any harm.
This will prevent whole kernel from building. So, for example, randconfig builds will fail.
makes a lot of sense, thank you
will rework so I reject to load if the requirement is not met
Quoted 12 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
drivers/gpu/drm/xen/xen_drm_front_shbuf.c new file +2
-0+ ret =gnttab_map_refs (map_ops,NULL , buf->pages, buf->num_pages); +BUG_ON (ret);Quoted 8 lines
Quoted 3 lines
We should try not to BUG*(). There are a few in this patch (and possibly others) that I think can be avoided.
I will rework BUG_* for map/unmap code to handle errors, but will still leave
/* either pages or sgt, not both */ BUG_ON(cfg->pages && cfg->sgt);which is a real driver bug and must not happen
Quoted 4 lines
Why not return an error?
In fact, AFAICS you only call it in patch 9 where both of these can be tested, in which case something like
-EINVALwould look reasonable.
ok, will remove BUG_ON as well
Quoted 1 line
-boris
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Re: [PATCH 5/9] drm/xen-front: Implement handling of shared display buffers
In reply to Boris OstrovskyQuoted 10 lines · Boris Ostrovsky
drivers/gpu/drm/xen/xen_drm_front.c static struct xenbus_driver xen_driver = { · line 204
Quoted 5 lines · Oleksandr Andrushchenko
static int __init xen_drv_init(void) {drivers/gpu/drm/xen/xen_drm_front.c +2
-0+/* At the moment we only support case with XEN_PAGE_SIZE == PAGE_SIZE */ +BUILD_BUG_ON (XEN_PAGE_SIZE !=PAGE_SIZE );Why
BUILD_BUG_ON? This should simply not load if page sizes are different.
This is a compile time check, so if kernel/Xen is configured to use page size combination which is not supported by the driver it will fail during compilation. This seems correct to me, because you shouldn't even try to load the driver which cannot handle different page sizes to not make any harm.
Quoted 9 lines
drivers/gpu/drm/xen/xen_drm_front_shbuf.c line 187
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front_shbuf.c new file +2
-0+ ret =gnttab_map_refs (map_ops,NULL , buf->pages, buf->num_pages); +BUG_ON (ret);We should try not to BUG*(). There are a few in this patch (and possibly others) that I think can be avoided.
I will rework BUG_* for map/unmap code to handle errors, but will still leave
/* either pages or sgt, not both */ BUG_ON(cfg->pages && cfg->sgt);
which is a real driver bug and must not happen
Quoted 17 lines
Quoted 17 lines
drivers/gpu/drm/xen/xen_drm_front_shbuf.c new file +14
-0+ +static int alloc_storage (struct xen_drm_front_shbuf *buf) +{ +if (buf->sgt) { + buf->pages =kvmalloc_array (buf->num_pages, +sizeof (struct page *),GFP_KERNEL ); +if (!buf->pages) +return -ENOMEM ; + +if (drm_prime_sg_to_page_addr_arrays (buf->sgt, buf->pages, +NULL , buf->num_pages) <0 ) +return -EINVAL ; + } +
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_shbuf.c line 367
Quoted 7 lines
drivers/gpu/drm/xen/xen_drm_front_shbuf.c new file +7
-0+ buf->grefs =kcalloc (buf->num_grefs,sizeof (*buf->grefs),GFP_KERNEL ); +if (!buf->grefs) +return -ENOMEM ; + + buf->directory =kcalloc (get_num_pages_dir (buf),PAGE_SIZE ,GFP_KERNEL ); +if (!buf->directory) +return -ENOMEM ;You need to clean up on errors.
this is called in xen_drm_front_shbuf_alloc and is properly cleaned on failure, e.g.:
ret = alloc_storage(buf);
if (ret)
goto fail;
[...]
fail:
xen_drm_front_shbuf_free(buf);
Quoted 5 lines
-boris
drivers/gpu/drm/xen/xen_drm_front_shbuf.c line 70
Quoted 3 lines
drivers/gpu/drm/xen/xen_drm_front_shbuf.c new file +3
-0+ +return 0 ; +}
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
PATCH 5/9 drm/xen-front: Implement handling of shared display buffers
In reply to Oleksandr AndrushchenkoFrom: Oleksandr Andrushchenko <[email protected]>
Implement shared buffer handling according to the para-virtualized display device protocol at xen/interface/io/displif.h:
- handle page directories according to displif protocol:
- allocate and share page directories
- grant references to the required set of pages for the page directory
- allocate xen balllooned pages via Xen balloon driver with alloc_xenballooned_pages/free_xenballooned_pages
- grant references to the required set of pages for the shared buffer itself
- implement pages map/unmap for the buffers allocated by the backend (gnttab_map_refs/gnttab_unmap_refs)
--- drivers/gpu/drm/xen/Makefile | 1 + drivers/gpu/drm/xen/xen_drm_front.c | 4 + drivers/gpu/drm/xen/xen_drm_front_shbuf.c | 430 ++++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_shbuf.h | 80 ++++++ 4 files changed, 515 insertions(+) create mode 100644 drivers/gpu/drm/xen/xen_drm_front_shbuf.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_shbuf.h
drivers/gpu/drm/xen/Makefile +1 -0
@@ -2,6 +2,7 @@ drm_xen_front-objs := xen_drm_front.o \ xen_drm_front_evtchnl.o \ + xen_drm_front_shbuf.o \ xen_drm_front_cfg.o obj-$(CONFIG_DRM_XEN_FRONTEND) += drm_xen_front.o
drivers/gpu/drm/xen/xen_drm_front.c +4 -0
@@ -26,6 +26,7 @@#include "xen_drm_front.h" #include "xen_drm_front_evtchnl.h" +#include "xen_drm_front_shbuf.h" static struct xen_drm_front_ops front_ops = {/* placeholder for now */
@@ -199,6 +200,9 @@ static struct xenbus_driver xen_driver = {static int __init xen_drv_init (void ) { +/* At the moment we only support case with XEN_PAGE_SIZE == PAGE_SIZE */ +BUILD_BUG_ON (XEN_PAGE_SIZE !=PAGE_SIZE ); +if (!xen_domain ())return -ENODEV ;
drivers/gpu/drm/xen/xen_drm_front_shbuf.c new file +430 -0
430 lines not on this page · raw message
drivers/gpu/drm/xen/xen_drm_front_shbuf.h new file +80 -0
80 lines not on this page · raw message
Signature · 7 lines
2.7.4 _______________________________________________ Xen-devel mailing list [email protected] https://lists.xenproject.org/mailman/listinfo/xen-devel
PATCH 6/9 drm/xen-front: Introduce DRM/KMS virtual display driver
In reply to Oleksandr AndrushchenkoFrom: Oleksandr Andrushchenko <[email protected]>
Implement essential initialization of the display driver:
- introduce required data structures
- handle DRM/KMS driver registration
- perform basic DRM driver initialization
- register driver on backend connection
- remove driver on backend disconnect
- introduce essential callbacks required by DRM/KMS core
- introduce essential callbacks required for frontend operations
--- drivers/gpu/drm/xen/Makefile | 1 + drivers/gpu/drm/xen/xen_drm_front.c | 169 ++++++++++++++++++++++++- drivers/gpu/drm/xen/xen_drm_front.h | 24 ++++ drivers/gpu/drm/xen/xen_drm_front_drv.c | 211 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_drv.h | 60 +++++++++ 5 files changed, 462 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/xen/xen_drm_front_drv.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_drv.h
drivers/gpu/drm/xen/Makefile +1 -0
@@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 drm_xen_front-objs := xen_drm_front.o \ + xen_drm_front_drv.o \ xen_drm_front_evtchnl.o \ xen_drm_front_shbuf.o \ xen_drm_front_cfg.o
drivers/gpu/drm/xen/xen_drm_front.c +166 -3
206 lines not on this page · raw message
drivers/gpu/drm/xen/xen_drm_front.h +24 -0
@@ -19,6 +19,8 @@#ifndef __XEN_DRM_FRONT_H_#define __XEN_DRM_FRONT_H_ +#include <linux/scatterlist.h> +#include "xen_drm_front_cfg.h" #ifndef GRANT_INVALID_REF
@@ -30,16 +32,38 @@#define GRANT_INVALID_REF 0#endif +struct xen_drm_front_drm_pipeline ; +struct xen_drm_front_ops { +int (*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); +int (*dbuf_create_from_pages)(struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct page **pages); +int (*dbuf_create_from_sgt)(struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct sg_table *sgt); +int (*dbuf_destroy)(struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie); +int (*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); +int (*fb_detach)(struct xen_drm_front_info *front_info, +uint64_t fb_cookie); +int (*page_flip)(struct xen_drm_front_info *front_info, +int conn_idx,uint64_t fb_cookie);/* CAUTION! this is called with a spin_lock held! */ void (*on_frame_done)(struct platform_device *pdev,int conn_idx,uint64_t fb_cookie); +void (*drm_last_close)(struct xen_drm_front_info *front_info); };struct xen_drm_front_info {struct xenbus_device *xb_dev;/* to protect data between backend IO code and interrupt handler */ spinlock_t io_lock; +bool drm_pdrv_registered;/* virtual DRM platform device */ struct platform_device *drm_pdev;
drivers/gpu/drm/xen/xen_drm_front_drv.c new file +211 -0
211 lines not on this page · raw message
drivers/gpu/drm/xen/xen_drm_front_drv.h new file +60 -0
60 lines not on this page · raw message
Signature · 6 lines
2.7.4 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 6/9] drm/xen-front: Introduce DRM/KMS virtual display driver
Quoted 11 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front_drv.c new file +11
-0+ +struct drm_driver xen_drm_driver = { + .driver_features =DRIVER_GEM |DRIVER_MODESET | +DRIVER_PRIME |DRIVER_ATOMIC , + .lastclose = lastclose, + .gem_free_object_unlocked = free_object, + .gem_vm_ops = &xen_drm_vm_ops, + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, + .gem_prime_import = drm_gem_prime_import, + .gem_prime_export = drm_gem_prime_export,
drivers/gpu/drm/xen/xen_drm_front_drv.c line 121
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front_drv.c new file +10
-0+ .gem_prime_get_sg_table = prime_get_sg_table, + .gem_prime_import_sg_table = prime_import_sg_table, + .gem_prime_vmap = prime_vmap, + .gem_prime_vunmap = prime_vunmap, + .gem_prime_mmap = prime_mmap, + .dumb_create = dumb_create, + .fops = &xendrm_fops, + .name = "xendrm-du", + .desc = "Xen PV DRM Display Unit", + .date = "20161109",
You must have been working on this for a while ;-)
I assume this needs to be updated.
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_drv.c new file +8
-0+bool xen_drm_front_drv_is_used (struct platform_device *pdev) +{ +struct xen_drm_front_drm_info *drm_info =platform_get_drvdata (pdev); +struct drm_device *dev; + +if (!drm_info) +return false; +
drivers/gpu/drm/xen/xen_drm_front_drv.c line 210
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front_drv.c new file +10
-0+ dev = drm_info->drm_dev; +if (!dev) +return false; + +/* +* FIXME: the code below must be protected by drm_global_mutex, +* but it is not accessible to us. Anyways there is a race condition, +* but we will re-try. +*/ +return dev->open_count !=0 ;
Would it be a problem, given the race, if you report that the frontend is not in use, while it actually is?
-boris
Re: [PATCH 6/9] drm/xen-front: Introduce DRM/KMS virtual display driver
Quoted 16 lines · Boris Ostrovsky
Quoted 14 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front_drv.c new file +14
-0+ +struct drm_driver xen_drm_driver = { + .driver_features =DRIVER_GEM |DRIVER_MODESET | +DRIVER_PRIME |DRIVER_ATOMIC , + .lastclose = lastclose, + .gem_free_object_unlocked = free_object, + .gem_vm_ops = &xen_drm_vm_ops, + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, + .gem_prime_import = drm_gem_prime_import, + .gem_prime_export = drm_gem_prime_export, + .gem_prime_get_sg_table = prime_get_sg_table, + .gem_prime_import_sg_table = prime_import_sg_table, + .gem_prime_vmap = prime_vmap,
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_drv.c line 121
Quoted 7 lines
drivers/gpu/drm/xen/xen_drm_front_drv.c new file +7
-0+ .gem_prime_vunmap = prime_vunmap, + .gem_prime_mmap = prime_mmap, + .dumb_create = dumb_create, + .fops = &xendrm_fops, + .name = "xendrm-du", + .desc = "Xen PV DRM Display Unit", + .date = "20161109",You must have been working on this for a while ;-)
yes, this is true ;)
Quoted 2 lines
I assume this needs to be updated.
It can be, but I would either stick to the current value for historical reasons or would update it in the final version of the driver, so it reflects the date of issuing ;)
Quoted 12 lines
Quoted 12 lines
drivers/gpu/drm/xen/xen_drm_front_drv.c new file +12
-0+bool xen_drm_front_drv_is_used (struct platform_device *pdev) +{ +struct xen_drm_front_drm_info *drm_info =platform_get_drvdata (pdev); +struct drm_device *dev; + +if (!drm_info) +return false; + + dev = drm_info->drm_dev; +if (!dev) +return false; +
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_drv.c line 210
Quoted 6 lines
drivers/gpu/drm/xen/xen_drm_front_drv.c new file +6
-0+/* +* FIXME: the code below must be protected by drm_global_mutex, +* but it is not accessible to us. Anyways there is a race condition, +* but we will re-try. +*/ +return dev->open_count !=0 ;Would it be a problem, given the race, if you report that the frontend is not in use, while it actually is?
no, backend will not be able to activate us again
Quoted 1 line
-boris
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 6/9] drm/xen-front: Introduce DRM/KMS virtual display driver
In reply to Boris OstrovskyQuoted 16 lines · Boris Ostrovsky
Quoted 14 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front_drv.c new file +14
-0+ +struct drm_driver xen_drm_driver = { + .driver_features =DRIVER_GEM |DRIVER_MODESET | +DRIVER_PRIME |DRIVER_ATOMIC , + .lastclose = lastclose, + .gem_free_object_unlocked = free_object, + .gem_vm_ops = &xen_drm_vm_ops, + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, + .gem_prime_import = drm_gem_prime_import, + .gem_prime_export = drm_gem_prime_export, + .gem_prime_get_sg_table = prime_get_sg_table, + .gem_prime_import_sg_table = prime_import_sg_table, + .gem_prime_vmap = prime_vmap,
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_drv.c line 121
Quoted 7 lines
drivers/gpu/drm/xen/xen_drm_front_drv.c new file +7
-0+ .gem_prime_vunmap = prime_vunmap, + .gem_prime_mmap = prime_mmap, + .dumb_create = dumb_create, + .fops = &xendrm_fops, + .name = "xendrm-du", + .desc = "Xen PV DRM Display Unit", + .date = "20161109",You must have been working on this for a while ;-)
yes, this is true ;)
Quoted 2 lines
I assume this needs to be updated.
It can be, but I would either stick to the current value for historical reasons or would update it in the final version of the driver, so it reflects the date of issuing ;)
Quoted 12 lines
Quoted 12 lines
drivers/gpu/drm/xen/xen_drm_front_drv.c new file +12
-0+bool xen_drm_front_drv_is_used (struct platform_device *pdev) +{ +struct xen_drm_front_drm_info *drm_info =platform_get_drvdata (pdev); +struct drm_device *dev; + +if (!drm_info) +return false; + + dev = drm_info->drm_dev; +if (!dev) +return false; +
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_drv.c line 210
Quoted 6 lines
drivers/gpu/drm/xen/xen_drm_front_drv.c new file +6
-0+/* +* FIXME: the code below must be protected by drm_global_mutex, +* but it is not accessible to us. Anyways there is a race condition, +* but we will re-try. +*/ +return dev->open_count !=0 ;Would it be a problem, given the race, if you report that the frontend is not in use, while it actually is?
no, backend will not be able to activate us again
Quoted 1 line
-boris
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Re: [PATCH 6/9] drm/xen-front: Introduce DRM/KMS virtual display driver
In reply to Oleksandr AndrushchenkoQuoted 122 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Implement essential initialization of the display driver:
- introduce required data structures
- handle DRM/KMS driver registration
- perform basic DRM driver initialization
- register driver on backend connection
- remove driver on backend disconnect
- introduce essential callbacks required by DRM/KMS core
- introduce essential callbacks required for frontend operationsSigned-off-by Oleksandr Andrushchenko <[email protected]>--- drivers/gpu/drm/xen/Makefile | 1 + drivers/gpu/drm/xen/xen_drm_front.c | 169 ++++++++++++++++++++++++- drivers/gpu/drm/xen/xen_drm_front.h | 24 ++++ drivers/gpu/drm/xen/xen_drm_front_drv.c | 211 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_drv.h | 60 +++++++++ 5 files changed, 462 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/xen/xen_drm_front_drv.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_drv.hdrivers/gpu/drm/xen/Makefile +1
-0@@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 drm_xen_front-objs := xen_drm_front.o \ + xen_drm_front_drv.o \ xen_drm_front_evtchnl.o \ xen_drm_front_shbuf.o \ xen_drm_front_cfg.odrivers/gpu/drm/xen/xen_drm_front.c +69
-0@@ -18,6 +18,8 @@#include <drm/drmP.h> +#include <linux/of_device.h> +#include <xen/platform_pci.h> #include <xen/xen.h> #include <xen/xenbus.h> @@ -25,15 +27,161 @@#include <xen/interface/io/displif.h> #include "xen_drm_front.h" +#include "xen_drm_front_drv.h" #include "xen_drm_front_evtchnl.h" #include "xen_drm_front_shbuf.h" +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 ; +} + +static int be_dbuf_create_int (struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct page **pages, +struct sg_table *sgt) +{ +return 0 ; +} + +static int be_dbuf_create_from_sgt (struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct sg_table *sgt) +{ +return be_dbuf_create_int (front_info, dbuf_cookie, width, height, + bpp, size,NULL , sgt); +} + +static int be_dbuf_create_from_pages (struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct page **pages) +{ +return be_dbuf_create_int (front_info, dbuf_cookie, width, height, + bpp, size, pages,NULL ); +} + +static int be_dbuf_destroy (struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie) +{ +return 0 ; +} + +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 ; +} + +static int be_fb_detach (struct xen_drm_front_info *front_info, +uint64_t fb_cookie) +{ +return 0 ; +} + +static int be_page_flip (struct xen_drm_front_info *front_info,int conn_idx, +uint64_t fb_cookie) +{ +return 0 ; +} + +static void xen_drm_drv_unload (struct xen_drm_front_info *front_info) +{ +if (front_info->xb_dev->state != XenbusStateReconfiguring) +return ; + +DRM_DEBUG ("Can try removing driver now\n" ); +xenbus_switch_state (front_info->xb_dev, XenbusStateInitialising); +} +static struct xen_drm_front_ops front_ops = {
drivers/gpu/drm/xen/xen_drm_front.c line 109
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front.c +9
-1-/* placeholder for now */ + .mode_set = be_mode_set, + .dbuf_create_from_pages = be_dbuf_create_from_pages, + .dbuf_create_from_sgt = be_dbuf_create_from_sgt, + .dbuf_destroy = be_dbuf_destroy, + .fb_attach = be_fb_attach, + .fb_detach = be_fb_detach, + .page_flip = be_page_flip, + .drm_last_close = xen_drm_drv_unload, +};
This looks like a midlayer/DRM-abstraction in your driver. Please remove, and instead directly hook your xen-front code into the relevant drm callbacks.
In general also pls make sure you don't implement dummy callbacks that do nothing, we've tried really hard to make them all optional in the drm infrastructure.
-Daniel
Quoted 458 lines
drivers/gpu/drm/xen/xen_drm_front.c +88
-2+ +static int xen_drm_drv_probe (struct platform_device *pdev) +{ +/* +* The device is not spawn from a device tree, so arch_setup_dma_ops +* is not called, thus leaving the device with dummy DMA ops. +* This makes the device return error on PRIME buffer import, which +* is not correct: to fix this call of_dma_configure() with a NULL +* node to set default DMA ops. +*/ +of_dma_configure (&pdev->dev,NULL ); +return xen_drm_front_drv_probe (pdev, &front_ops); +} + +static int xen_drm_drv_remove (struct platform_device *pdev) +{ +return xen_drm_front_drv_remove (pdev); +} + +struct platform_device_info xen_drm_front_platform_info = { + .name =XENDISPL_DRIVER_NAME , + .id =0 , + .num_res =0 , + .dma_mask =DMA_BIT_MASK (32 ), }; +static struct platform_driver xen_drm_front_front_info = { + .probe = xen_drm_drv_probe, + .remove = xen_drm_drv_remove, + .driver = { + .name =XENDISPL_DRIVER_NAME , + }, +}; + +static void xen_drm_drv_deinit (struct xen_drm_front_info *front_info) +{ +if (!front_info->drm_pdrv_registered) +return ; + +if (front_info->drm_pdev) +platform_device_unregister (front_info->drm_pdev); + +platform_driver_unregister (&xen_drm_front_front_info); + front_info->drm_pdrv_registered = false; + front_info->drm_pdev =NULL ; +} + +static int xen_drm_drv_init (struct xen_drm_front_info *front_info) +{ +int ret; + + ret =platform_driver_register (&xen_drm_front_front_info); +if (ret <0 ) +return ret; + + front_info->drm_pdrv_registered = true; +/* pass card configuration via platform data */ + xen_drm_front_platform_info.data = &front_info->cfg; + xen_drm_front_platform_info.size_data =sizeof (front_info->cfg); + + front_info->drm_pdev =platform_device_register_full ( + &xen_drm_front_platform_info); +if (IS_ERR_OR_NULL (front_info->drm_pdev)) { +DRM_ERROR ("Failed to register " XENDISPL_DRIVER_NAME " PV DRM driver\n" ); + front_info->drm_pdev =NULL ; +xen_drm_drv_deinit (front_info); +return -ENODEV ; + } + +return 0 ; +} +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); }@@ -59,13 +207,27 @@ static int backend_on_initwait(struct xen_drm_front_info *front_info)static int backend_on_connected (struct xen_drm_front_info *front_info) {xen_drm_front_evtchnl_set_state (front_info,EVTCHNL_STATE_CONNECTED ); -return 0 ; +return xen_drm_drv_init (front_info); }static void backend_on_disconnected (struct xen_drm_front_info *front_info) { +bool removed = true; + +if (front_info->drm_pdev) { +if (xen_drm_front_drv_is_used (front_info->drm_pdev)) { +DRM_WARN ("DRM driver still in use, deferring removal\n" ); + removed = false; + }else +xen_drv_remove_internal (front_info); + } +xen_drm_front_evtchnl_set_state (front_info,EVTCHNL_STATE_DISCONNECTED ); -xenbus_switch_state (front_info->xb_dev, XenbusStateInitialising); + +if (removed) +xenbus_switch_state (front_info->xb_dev, XenbusStateInitialising); +else +xenbus_switch_state (front_info->xb_dev, XenbusStateReconfiguring); } static void backend_on_changed(struct xenbus_device *xb_dev,@@ -148,6 +310,7 @@ static int xen_drv_probe(struct xenbus_device *xb_dev, front_info->xb_dev = xb_dev;spin_lock_init (&front_info->io_lock); + front_info->drm_pdrv_registered = false;dev_set_drvdata (&xb_dev->dev, front_info);return xenbus_switch_state (xb_dev, XenbusStateInitialising); }drivers/gpu/drm/xen/xen_drm_front.h +24
-0@@ -19,6 +19,8 @@#ifndef __XEN_DRM_FRONT_H_#define __XEN_DRM_FRONT_H_ +#include <linux/scatterlist.h> +#include "xen_drm_front_cfg.h" #ifndef GRANT_INVALID_REF @@ -30,16 +32,38 @@#define GRANT_INVALID_REF 0#endif +struct xen_drm_front_drm_pipeline ; +struct xen_drm_front_ops { +int (*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); +int (*dbuf_create_from_pages)(struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct page **pages); +int (*dbuf_create_from_sgt)(struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct sg_table *sgt); +int (*dbuf_destroy)(struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie); +int (*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); +int (*fb_detach)(struct xen_drm_front_info *front_info, +uint64_t fb_cookie); +int (*page_flip)(struct xen_drm_front_info *front_info, +int conn_idx,uint64_t fb_cookie);/* CAUTION! this is called with a spin_lock held! */ void (*on_frame_done)(struct platform_device *pdev,int conn_idx,uint64_t fb_cookie); +void (*drm_last_close)(struct xen_drm_front_info *front_info); };struct xen_drm_front_info {struct xenbus_device *xb_dev;/* to protect data between backend IO code and interrupt handler */ spinlock_t io_lock; +bool drm_pdrv_registered;/* virtual DRM platform device */ struct platform_device *drm_pdev;drivers/gpu/drm/xen/xen_drm_front_drv.c new file +211
-0@@ -0,0 +1,211 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include <drm/drmP.h> +#include <drm/drm_gem.h> +#include <drm/drm_atomic_helper.h> + +#include "xen_drm_front.h" +#include "xen_drm_front_cfg.h" +#include "xen_drm_front_drv.h" + +static int dumb_create (struct drm_file *filp, +struct drm_device *dev,struct drm_mode_create_dumb *args) +{ +return -EINVAL ; +} + +static void free_object (struct drm_gem_object *obj) +{ +struct xen_drm_front_drm_info *drm_info = obj->dev->dev_private; + + drm_info->front_ops->dbuf_destroy (drm_info->front_info, +xen_drm_front_dbuf_to_cookie (obj)); +} + +static void on_frame_done (struct platform_device *pdev, +int conn_idx,uint64_t fb_cookie) +{ +} + +static void lastclose (struct drm_device *dev) +{ +struct xen_drm_front_drm_info *drm_info = dev->dev_private; + + drm_info->front_ops->drm_last_close (drm_info->front_info); +} + +static int gem_mmap (struct file *filp,struct vm_area_struct *vma) +{ +return -EINVAL ; +} + +static struct sg_table *prime_get_sg_table (struct drm_gem_object *obj) +{ +return NULL ; +} + +static struct drm_gem_object *prime_import_sg_table (struct drm_device *dev, +struct dma_buf_attachment *attach,struct sg_table *sgt) +{ +return NULL ; +} + +static void *prime_vmap (struct drm_gem_object *obj) +{ +return NULL ; +} + +static void prime_vunmap (struct drm_gem_object *obj,void *vaddr) +{ +} + +static int prime_mmap (struct drm_gem_object *obj,struct vm_area_struct *vma) +{ +return -EINVAL ; +} + +static const struct file_operations xendrm_fops = { + .owner =THIS_MODULE , + .open = drm_open, + .release = drm_release, + .unlocked_ioctl = drm_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif + .poll = drm_poll, + .read = drm_read, + .llseek = no_llseek, + .mmap = gem_mmap, +}; + +static const struct vm_operations_struct xen_drm_vm_ops = { + .open = drm_gem_vm_open, + .close = drm_gem_vm_close, +}; + +struct drm_driver xen_drm_driver = { + .driver_features =DRIVER_GEM |DRIVER_MODESET | +DRIVER_PRIME |DRIVER_ATOMIC , + .lastclose = lastclose, + .gem_free_object_unlocked = free_object, + .gem_vm_ops = &xen_drm_vm_ops, + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, + .gem_prime_import = drm_gem_prime_import, + .gem_prime_export = drm_gem_prime_export, + .gem_prime_get_sg_table = prime_get_sg_table, + .gem_prime_import_sg_table = prime_import_sg_table, + .gem_prime_vmap = prime_vmap, + .gem_prime_vunmap = prime_vunmap, + .gem_prime_mmap = prime_mmap, + .dumb_create = dumb_create, + .fops = &xendrm_fops, + .name ="xendrm-du" , + .desc ="Xen PV DRM Display Unit" , + .date ="20161109" , + .major =1 , + .minor =0 , +}; + +int xen_drm_front_drv_probe (struct platform_device *pdev, +struct xen_drm_front_ops *front_ops) +{ +struct xen_drm_front_cfg *cfg =dev_get_platdata (&pdev->dev); +struct xen_drm_front_drm_info *drm_info; +struct drm_device *dev; +int ret; + +DRM_INFO ("Creating %s\n" , xen_drm_driver.desc); + + drm_info =devm_kzalloc (&pdev->dev,sizeof (*drm_info),GFP_KERNEL ); +if (!drm_info) +return -ENOMEM ; + + drm_info->front_ops = front_ops; + drm_info->front_ops->on_frame_done = on_frame_done; + drm_info->front_info = cfg->front_info; + + dev =drm_dev_alloc (&xen_drm_driver, &pdev->dev); +if (!dev) +return -ENOMEM ; + + drm_info->drm_dev = dev; + + drm_info->cfg = cfg; + dev->dev_private = drm_info; +platform_set_drvdata (pdev, drm_info); + + ret =drm_vblank_init (dev, cfg->num_connectors); +if (ret) { +DRM_ERROR ("Failed to initialize vblank, ret %d\n" , ret); +return ret; + } + + dev->irq_enabled =1 ; + + ret =drm_dev_register (dev,0 ); +if (ret) + goto fail_register; + +DRM_INFO ("Initialized %s %d.%d.%d %s on minor %d\n" , + xen_drm_driver.name, xen_drm_driver.major, + xen_drm_driver.minor, xen_drm_driver.patchlevel, + xen_drm_driver.date, dev->primary->index); + +return 0 ; + +fail_register: +drm_dev_unregister (dev); +drm_mode_config_cleanup (dev); +return ret; +} + +int xen_drm_front_drv_remove (struct platform_device *pdev) +{ +struct xen_drm_front_drm_info *drm_info =platform_get_drvdata (pdev); +struct drm_device *dev = drm_info->drm_dev; + +if (dev) { +drm_dev_unregister (dev); +drm_atomic_helper_shutdown (dev); +drm_mode_config_cleanup (dev); +drm_dev_unref (dev); + } +return 0 ; +} + +bool xen_drm_front_drv_is_used (struct platform_device *pdev) +{ +struct xen_drm_front_drm_info *drm_info =platform_get_drvdata (pdev); +struct drm_device *dev; + +if (!drm_info) +return false; + + dev = drm_info->drm_dev; +if (!dev) +return false; + +/* +* FIXME: the code below must be protected by drm_global_mutex, +* but it is not accessible to us. Anyways there is a race condition, +* but we will re-try. +*/ +return dev->open_count !=0 ; +}drivers/gpu/drm/xen/xen_drm_front_drv.h new file +60
-0@@ -0,0 +1,60 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_DRV_H_ +#define __XEN_DRM_FRONT_DRV_H_ + +#include <drm/drmP.h> + +#include "xen_drm_front.h" +#include "xen_drm_front_cfg.h" + +struct xen_drm_front_drm_pipeline { +struct xen_drm_front_drm_info *drm_info; + +int index; +}; + +struct xen_drm_front_drm_info { +struct xen_drm_front_info *front_info; +struct xen_drm_front_ops *front_ops; +struct drm_device *drm_dev; +struct xen_drm_front_cfg *cfg; +}; + +static inline uint64_t xen_drm_front_fb_to_cookie ( +struct drm_framebuffer *fb) +{ +return (uint64_t )fb; +} + +static inline uint64_t xen_drm_front_dbuf_to_cookie ( +struct drm_gem_object *gem_obj) +{ +return (uint64_t )gem_obj; +} + +int xen_drm_front_drv_probe (struct platform_device *pdev, +struct xen_drm_front_ops *front_ops); + +int xen_drm_front_drv_remove (struct platform_device *pdev); + +bool xen_drm_front_drv_is_used (struct platform_device *pdev); + +#endif /* __XEN_DRM_FRONT_DRV_H_ */ +Signature · 6 lines
2.7.4 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Signature · 7 lines
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 6/9] drm/xen-front: Introduce DRM/KMS virtual display driver
Quoted 128 lines · Daniel Vetter
Quoted 127 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Implement essential initialization of the display driver:
- introduce required data structures
- handle DRM/KMS driver registration
- perform basic DRM driver initialization
- register driver on backend connection
- remove driver on backend disconnect
- introduce essential callbacks required by DRM/KMS core
- introduce essential callbacks required for frontend operationsSigned-off-by Oleksandr Andrushchenko <[email protected]>--- drivers/gpu/drm/xen/Makefile | 1 + drivers/gpu/drm/xen/xen_drm_front.c | 169 ++++++++++++++++++++++++- drivers/gpu/drm/xen/xen_drm_front.h | 24 ++++ drivers/gpu/drm/xen/xen_drm_front_drv.c | 211 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_drv.h | 60 +++++++++ 5 files changed, 462 insertions(+), 3 deletions(-)create mode 100644
drivers/gpu/drm/xen/xen_drm_front_drv.ccreate mode 100644drivers/gpu/drm/xen/xen_drm_front_drv.hdrivers/gpu/drm/xen/Makefile +1
-0@@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 drm_xen_front-objs := xen_drm_front.o \ + xen_drm_front_drv.o \ xen_drm_front_evtchnl.o \ xen_drm_front_shbuf.o \ xen_drm_front_cfg.odrivers/gpu/drm/xen/xen_drm_front.c +73
-1@@ -18,6 +18,8 @@#include <drm/drmP.h> +#include <linux/of_device.h> +#include <xen/platform_pci.h> #include <xen/xen.h> #include <xen/xenbus.h> @@ -25,15 +27,161 @@#include <xen/interface/io/displif.h> #include "xen_drm_front.h" +#include "xen_drm_front_drv.h" #include "xen_drm_front_evtchnl.h" #include "xen_drm_front_shbuf.h" +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 ; +} + +static int be_dbuf_create_int (struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct page **pages, +struct sg_table *sgt) +{ +return 0 ; +} + +static int be_dbuf_create_from_sgt (struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct sg_table *sgt) +{ +return be_dbuf_create_int (front_info, dbuf_cookie, width, height, + bpp, size,NULL , sgt); +} + +static int be_dbuf_create_from_pages (struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct page **pages) +{ +return be_dbuf_create_int (front_info, dbuf_cookie, width, height, + bpp, size, pages,NULL ); +} + +static int be_dbuf_destroy (struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie) +{ +return 0 ; +} + +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 ; +} + +static int be_fb_detach (struct xen_drm_front_info *front_info, +uint64_t fb_cookie) +{ +return 0 ; +} + +static int be_page_flip (struct xen_drm_front_info *front_info,int conn_idx, +uint64_t fb_cookie) +{ +return 0 ; +} + +static void xen_drm_drv_unload (struct xen_drm_front_info *front_info) +{ +if (front_info->xb_dev->state != XenbusStateReconfiguring) +return ; + +DRM_DEBUG ("Can try removing driver now\n" ); +xenbus_switch_state (front_info->xb_dev, XenbusStateInitialising); +} +static struct xen_drm_front_ops front_ops = { -/* placeholder for now */ + .mode_set = be_mode_set, + .dbuf_create_from_pages = be_dbuf_create_from_pages, + .dbuf_create_from_sgt = be_dbuf_create_from_sgt, + .dbuf_destroy = be_dbuf_destroy,
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front.c line 109
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front.c +5
-0+ .fb_attach = be_fb_attach, + .fb_detach = be_fb_detach, + .page_flip = be_page_flip, + .drm_last_close = xen_drm_drv_unload, +};This looks like a midlayer/DRM-abstraction in your driver. Please remove, and instead directly hook your xen-front code into the relevant drm callbacks.
ok, will do
Quoted 4 lines
In general also pls make sure you don't implement dummy callbacks that do nothing, we've tried really hard to make them all optional in the drm infrastructure.
sure
Quoted 456 lines
-Daniel
Quoted 454 lines
drivers/gpu/drm/xen/xen_drm_front.c +88
-2+ +static int xen_drm_drv_probe (struct platform_device *pdev) +{ +/* +* The device is not spawn from a device tree, so arch_setup_dma_ops +* is not called, thus leaving the device with dummy DMA ops. +* This makes the device return error on PRIME buffer import, which +* is not correct: to fix this call of_dma_configure() with a NULL +* node to set default DMA ops. +*/ +of_dma_configure (&pdev->dev,NULL ); +return xen_drm_front_drv_probe (pdev, &front_ops); +} + +static int xen_drm_drv_remove (struct platform_device *pdev) +{ +return xen_drm_front_drv_remove (pdev); +} + +struct platform_device_info xen_drm_front_platform_info = { + .name =XENDISPL_DRIVER_NAME , + .id =0 , + .num_res =0 , + .dma_mask =DMA_BIT_MASK (32 ), }; +static struct platform_driver xen_drm_front_front_info = { + .probe = xen_drm_drv_probe, + .remove = xen_drm_drv_remove, + .driver = { + .name =XENDISPL_DRIVER_NAME , + }, +}; + +static void xen_drm_drv_deinit (struct xen_drm_front_info *front_info) +{ +if (!front_info->drm_pdrv_registered) +return ; + +if (front_info->drm_pdev) +platform_device_unregister (front_info->drm_pdev); + +platform_driver_unregister (&xen_drm_front_front_info); + front_info->drm_pdrv_registered = false; + front_info->drm_pdev =NULL ; +} + +static int xen_drm_drv_init (struct xen_drm_front_info *front_info) +{ +int ret; + + ret =platform_driver_register (&xen_drm_front_front_info); +if (ret <0 ) +return ret; + + front_info->drm_pdrv_registered = true; +/* pass card configuration via platform data */ + xen_drm_front_platform_info.data = &front_info->cfg; + xen_drm_front_platform_info.size_data =sizeof (front_info->cfg); + + front_info->drm_pdev =platform_device_register_full ( + &xen_drm_front_platform_info); +if (IS_ERR_OR_NULL (front_info->drm_pdev)) { +DRM_ERROR ("Failed to register " XENDISPL_DRIVER_NAME " PV DRM driver\n" ); + front_info->drm_pdev =NULL ; +xen_drm_drv_deinit (front_info); +return -ENODEV ; + } + +return 0 ; +} +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); }@@ -59,13 +207,27 @@ static int backend_on_initwait(struct xen_drm_front_info *front_info)static int backend_on_connected (struct xen_drm_front_info *front_info) {xen_drm_front_evtchnl_set_state (front_info,EVTCHNL_STATE_CONNECTED ); -return 0 ; +return xen_drm_drv_init (front_info); }static void backend_on_disconnected (struct xen_drm_front_info *front_info) { +bool removed = true; + +if (front_info->drm_pdev) { +if (xen_drm_front_drv_is_used (front_info->drm_pdev)) { +DRM_WARN ("DRM driver still in use, deferring removal\n" ); + removed = false; + }else +xen_drv_remove_internal (front_info); + } +xen_drm_front_evtchnl_set_state (front_info,EVTCHNL_STATE_DISCONNECTED ); -xenbus_switch_state (front_info->xb_dev, XenbusStateInitialising); + +if (removed) +xenbus_switch_state (front_info->xb_dev, XenbusStateInitialising); +else +xenbus_switch_state (front_info->xb_dev, XenbusStateReconfiguring); } static void backend_on_changed(struct xenbus_device *xb_dev,@@ -148,6 +310,7 @@ static int xen_drv_probe(struct xenbus_device *xb_dev, front_info->xb_dev = xb_dev;spin_lock_init (&front_info->io_lock); + front_info->drm_pdrv_registered = false;dev_set_drvdata (&xb_dev->dev, front_info);return xenbus_switch_state (xb_dev, XenbusStateInitialising); }drivers/gpu/drm/xen/xen_drm_front.h +24
-0@@ -19,6 +19,8 @@#ifndef __XEN_DRM_FRONT_H_#define __XEN_DRM_FRONT_H_ +#include <linux/scatterlist.h> +#include "xen_drm_front_cfg.h" #ifndef GRANT_INVALID_REF @@ -30,16 +32,38 @@#define GRANT_INVALID_REF 0#endif +struct xen_drm_front_drm_pipeline ; +struct xen_drm_front_ops { +int (*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); +int (*dbuf_create_from_pages)(struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct page **pages); +int (*dbuf_create_from_sgt)(struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct sg_table *sgt); +int (*dbuf_destroy)(struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie); +int (*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); +int (*fb_detach)(struct xen_drm_front_info *front_info, +uint64_t fb_cookie); +int (*page_flip)(struct xen_drm_front_info *front_info, +int conn_idx,uint64_t fb_cookie);/* CAUTION! this is called with a spin_lock held! */ void (*on_frame_done)(struct platform_device *pdev,int conn_idx,uint64_t fb_cookie); +void (*drm_last_close)(struct xen_drm_front_info *front_info); };struct xen_drm_front_info {struct xenbus_device *xb_dev;/* to protect data between backend IO code and interrupt handler */ spinlock_t io_lock; +bool drm_pdrv_registered;/* virtual DRM platform device */ struct platform_device *drm_pdev;drivers/gpu/drm/xen/xen_drm_front_drv.c new file +211
-0@@ -0,0 +1,211 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include <drm/drmP.h> +#include <drm/drm_gem.h> +#include <drm/drm_atomic_helper.h> + +#include "xen_drm_front.h" +#include "xen_drm_front_cfg.h" +#include "xen_drm_front_drv.h" + +static int dumb_create (struct drm_file *filp, +struct drm_device *dev,struct drm_mode_create_dumb *args) +{ +return -EINVAL ; +} + +static void free_object (struct drm_gem_object *obj) +{ +struct xen_drm_front_drm_info *drm_info = obj->dev->dev_private; + + drm_info->front_ops->dbuf_destroy (drm_info->front_info, +xen_drm_front_dbuf_to_cookie (obj)); +} + +static void on_frame_done (struct platform_device *pdev, +int conn_idx,uint64_t fb_cookie) +{ +} + +static void lastclose (struct drm_device *dev) +{ +struct xen_drm_front_drm_info *drm_info = dev->dev_private; + + drm_info->front_ops->drm_last_close (drm_info->front_info); +} + +static int gem_mmap (struct file *filp,struct vm_area_struct *vma) +{ +return -EINVAL ; +} + +static struct sg_table *prime_get_sg_table (struct drm_gem_object *obj) +{ +return NULL ; +} + +static struct drm_gem_object *prime_import_sg_table (struct drm_device *dev, +struct dma_buf_attachment *attach,struct sg_table *sgt) +{ +return NULL ; +} + +static void *prime_vmap (struct drm_gem_object *obj) +{ +return NULL ; +} + +static void prime_vunmap (struct drm_gem_object *obj,void *vaddr) +{ +} + +static int prime_mmap (struct drm_gem_object *obj,struct vm_area_struct *vma) +{ +return -EINVAL ; +} + +static const struct file_operations xendrm_fops = { + .owner =THIS_MODULE , + .open = drm_open, + .release = drm_release, + .unlocked_ioctl = drm_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif + .poll = drm_poll, + .read = drm_read, + .llseek = no_llseek, + .mmap = gem_mmap, +}; + +static const struct vm_operations_struct xen_drm_vm_ops = { + .open = drm_gem_vm_open, + .close = drm_gem_vm_close, +}; + +struct drm_driver xen_drm_driver = { + .driver_features =DRIVER_GEM |DRIVER_MODESET | +DRIVER_PRIME |DRIVER_ATOMIC , + .lastclose = lastclose, + .gem_free_object_unlocked = free_object, + .gem_vm_ops = &xen_drm_vm_ops, + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, + .gem_prime_import = drm_gem_prime_import, + .gem_prime_export = drm_gem_prime_export, + .gem_prime_get_sg_table = prime_get_sg_table, + .gem_prime_import_sg_table = prime_import_sg_table, + .gem_prime_vmap = prime_vmap, + .gem_prime_vunmap = prime_vunmap, + .gem_prime_mmap = prime_mmap, + .dumb_create = dumb_create, + .fops = &xendrm_fops, + .name ="xendrm-du" , + .desc ="Xen PV DRM Display Unit" , + .date ="20161109" , + .major =1 , + .minor =0 , +}; + +int xen_drm_front_drv_probe (struct platform_device *pdev, +struct xen_drm_front_ops *front_ops) +{ +struct xen_drm_front_cfg *cfg =dev_get_platdata (&pdev->dev); +struct xen_drm_front_drm_info *drm_info; +struct drm_device *dev; +int ret; + +DRM_INFO ("Creating %s\n" , xen_drm_driver.desc); + + drm_info =devm_kzalloc (&pdev->dev,sizeof (*drm_info),GFP_KERNEL ); +if (!drm_info) +return -ENOMEM ; + + drm_info->front_ops = front_ops; + drm_info->front_ops->on_frame_done = on_frame_done; + drm_info->front_info = cfg->front_info; + + dev =drm_dev_alloc (&xen_drm_driver, &pdev->dev); +if (!dev) +return -ENOMEM ; + + drm_info->drm_dev = dev; + + drm_info->cfg = cfg; + dev->dev_private = drm_info; +platform_set_drvdata (pdev, drm_info); + + ret =drm_vblank_init (dev, cfg->num_connectors); +if (ret) { +DRM_ERROR ("Failed to initialize vblank, ret %d\n" , ret); +return ret; + } + + dev->irq_enabled =1 ; + + ret =drm_dev_register (dev,0 ); +if (ret) + goto fail_register; + +DRM_INFO ("Initialized %s %d.%d.%d %s on minor %d\n" , + xen_drm_driver.name, xen_drm_driver.major, + xen_drm_driver.minor, xen_drm_driver.patchlevel, + xen_drm_driver.date, dev->primary->index); + +return 0 ; + +fail_register: +drm_dev_unregister (dev); +drm_mode_config_cleanup (dev); +return ret; +} + +int xen_drm_front_drv_remove (struct platform_device *pdev) +{ +struct xen_drm_front_drm_info *drm_info =platform_get_drvdata (pdev); +struct drm_device *dev = drm_info->drm_dev; + +if (dev) { +drm_dev_unregister (dev); +drm_atomic_helper_shutdown (dev); +drm_mode_config_cleanup (dev); +drm_dev_unref (dev); + } +return 0 ; +} + +bool xen_drm_front_drv_is_used (struct platform_device *pdev) +{ +struct xen_drm_front_drm_info *drm_info =platform_get_drvdata (pdev); +struct drm_device *dev; + +if (!drm_info) +return false; + + dev = drm_info->drm_dev; +if (!dev) +return false; + +/* +* FIXME: the code below must be protected by drm_global_mutex, +* but it is not accessible to us. Anyways there is a race condition, +* but we will re-try. +*/ +return dev->open_count !=0 ; +}drivers/gpu/drm/xen/xen_drm_front_drv.h new file +60
-0@@ -0,0 +1,60 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_DRV_H_ +#define __XEN_DRM_FRONT_DRV_H_ + +#include <drm/drmP.h> + +#include "xen_drm_front.h" +#include "xen_drm_front_cfg.h" + +struct xen_drm_front_drm_pipeline { +struct xen_drm_front_drm_info *drm_info; + +int index; +}; + +struct xen_drm_front_drm_info { +struct xen_drm_front_info *front_info; +struct xen_drm_front_ops *front_ops; +struct drm_device *drm_dev; +struct xen_drm_front_cfg *cfg; +}; + +static inline uint64_t xen_drm_front_fb_to_cookie ( +struct drm_framebuffer *fb) +{ +return (uint64_t )fb; +} + +static inline uint64_t xen_drm_front_dbuf_to_cookie ( +struct drm_gem_object *gem_obj) +{ +return (uint64_t )gem_obj; +} + +int xen_drm_front_drv_probe (struct platform_device *pdev, +struct xen_drm_front_ops *front_ops); + +int xen_drm_front_drv_remove (struct platform_device *pdev); + +bool xen_drm_front_drv_is_used (struct platform_device *pdev); + +#endif /* __XEN_DRM_FRONT_DRV_H_ */ +Signature · 1 line
2.7.4
Quoted 4 lines
Quoted 4 lines
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 6/9] drm/xen-front: Introduce DRM/KMS virtual display driver
In reply to Daniel VetterQuoted 128 lines · Daniel Vetter
Quoted 127 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Implement essential initialization of the display driver:
- introduce required data structures
- handle DRM/KMS driver registration
- perform basic DRM driver initialization
- register driver on backend connection
- remove driver on backend disconnect
- introduce essential callbacks required by DRM/KMS core
- introduce essential callbacks required for frontend operationsSigned-off-by Oleksandr Andrushchenko <[email protected]>--- drivers/gpu/drm/xen/Makefile | 1 + drivers/gpu/drm/xen/xen_drm_front.c | 169 ++++++++++++++++++++++++- drivers/gpu/drm/xen/xen_drm_front.h | 24 ++++ drivers/gpu/drm/xen/xen_drm_front_drv.c | 211 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_drv.h | 60 +++++++++ 5 files changed, 462 insertions(+), 3 deletions(-)create mode 100644
drivers/gpu/drm/xen/xen_drm_front_drv.ccreate mode 100644drivers/gpu/drm/xen/xen_drm_front_drv.hdrivers/gpu/drm/xen/Makefile +1
-0@@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 drm_xen_front-objs := xen_drm_front.o \ + xen_drm_front_drv.o \ xen_drm_front_evtchnl.o \ xen_drm_front_shbuf.o \ xen_drm_front_cfg.odrivers/gpu/drm/xen/xen_drm_front.c +73
-1@@ -18,6 +18,8 @@#include <drm/drmP.h> +#include <linux/of_device.h> +#include <xen/platform_pci.h> #include <xen/xen.h> #include <xen/xenbus.h> @@ -25,15 +27,161 @@#include <xen/interface/io/displif.h> #include "xen_drm_front.h" +#include "xen_drm_front_drv.h" #include "xen_drm_front_evtchnl.h" #include "xen_drm_front_shbuf.h" +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 ; +} + +static int be_dbuf_create_int (struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct page **pages, +struct sg_table *sgt) +{ +return 0 ; +} + +static int be_dbuf_create_from_sgt (struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct sg_table *sgt) +{ +return be_dbuf_create_int (front_info, dbuf_cookie, width, height, + bpp, size,NULL , sgt); +} + +static int be_dbuf_create_from_pages (struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct page **pages) +{ +return be_dbuf_create_int (front_info, dbuf_cookie, width, height, + bpp, size, pages,NULL ); +} + +static int be_dbuf_destroy (struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie) +{ +return 0 ; +} + +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 ; +} + +static int be_fb_detach (struct xen_drm_front_info *front_info, +uint64_t fb_cookie) +{ +return 0 ; +} + +static int be_page_flip (struct xen_drm_front_info *front_info,int conn_idx, +uint64_t fb_cookie) +{ +return 0 ; +} + +static void xen_drm_drv_unload (struct xen_drm_front_info *front_info) +{ +if (front_info->xb_dev->state != XenbusStateReconfiguring) +return ; + +DRM_DEBUG ("Can try removing driver now\n" ); +xenbus_switch_state (front_info->xb_dev, XenbusStateInitialising); +} +static struct xen_drm_front_ops front_ops = { -/* placeholder for now */ + .mode_set = be_mode_set, + .dbuf_create_from_pages = be_dbuf_create_from_pages, + .dbuf_create_from_sgt = be_dbuf_create_from_sgt, + .dbuf_destroy = be_dbuf_destroy,
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front.c line 109
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front.c +5
-0+ .fb_attach = be_fb_attach, + .fb_detach = be_fb_detach, + .page_flip = be_page_flip, + .drm_last_close = xen_drm_drv_unload, +};This looks like a midlayer/DRM-abstraction in your driver. Please remove, and instead directly hook your xen-front code into the relevant drm callbacks.
ok, will do
Quoted 4 lines
In general also pls make sure you don't implement dummy callbacks that do nothing, we've tried really hard to make them all optional in the drm infrastructure.
sure
Quoted 456 lines
-Daniel
Quoted 454 lines
drivers/gpu/drm/xen/xen_drm_front.c +88
-2+ +static int xen_drm_drv_probe (struct platform_device *pdev) +{ +/* +* The device is not spawn from a device tree, so arch_setup_dma_ops +* is not called, thus leaving the device with dummy DMA ops. +* This makes the device return error on PRIME buffer import, which +* is not correct: to fix this call of_dma_configure() with a NULL +* node to set default DMA ops. +*/ +of_dma_configure (&pdev->dev,NULL ); +return xen_drm_front_drv_probe (pdev, &front_ops); +} + +static int xen_drm_drv_remove (struct platform_device *pdev) +{ +return xen_drm_front_drv_remove (pdev); +} + +struct platform_device_info xen_drm_front_platform_info = { + .name =XENDISPL_DRIVER_NAME , + .id =0 , + .num_res =0 , + .dma_mask =DMA_BIT_MASK (32 ), }; +static struct platform_driver xen_drm_front_front_info = { + .probe = xen_drm_drv_probe, + .remove = xen_drm_drv_remove, + .driver = { + .name =XENDISPL_DRIVER_NAME , + }, +}; + +static void xen_drm_drv_deinit (struct xen_drm_front_info *front_info) +{ +if (!front_info->drm_pdrv_registered) +return ; + +if (front_info->drm_pdev) +platform_device_unregister (front_info->drm_pdev); + +platform_driver_unregister (&xen_drm_front_front_info); + front_info->drm_pdrv_registered = false; + front_info->drm_pdev =NULL ; +} + +static int xen_drm_drv_init (struct xen_drm_front_info *front_info) +{ +int ret; + + ret =platform_driver_register (&xen_drm_front_front_info); +if (ret <0 ) +return ret; + + front_info->drm_pdrv_registered = true; +/* pass card configuration via platform data */ + xen_drm_front_platform_info.data = &front_info->cfg; + xen_drm_front_platform_info.size_data =sizeof (front_info->cfg); + + front_info->drm_pdev =platform_device_register_full ( + &xen_drm_front_platform_info); +if (IS_ERR_OR_NULL (front_info->drm_pdev)) { +DRM_ERROR ("Failed to register " XENDISPL_DRIVER_NAME " PV DRM driver\n" ); + front_info->drm_pdev =NULL ; +xen_drm_drv_deinit (front_info); +return -ENODEV ; + } + +return 0 ; +} +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); }@@ -59,13 +207,27 @@ static int backend_on_initwait(struct xen_drm_front_info *front_info)static int backend_on_connected (struct xen_drm_front_info *front_info) {xen_drm_front_evtchnl_set_state (front_info,EVTCHNL_STATE_CONNECTED ); -return 0 ; +return xen_drm_drv_init (front_info); }static void backend_on_disconnected (struct xen_drm_front_info *front_info) { +bool removed = true; + +if (front_info->drm_pdev) { +if (xen_drm_front_drv_is_used (front_info->drm_pdev)) { +DRM_WARN ("DRM driver still in use, deferring removal\n" ); + removed = false; + }else +xen_drv_remove_internal (front_info); + } +xen_drm_front_evtchnl_set_state (front_info,EVTCHNL_STATE_DISCONNECTED ); -xenbus_switch_state (front_info->xb_dev, XenbusStateInitialising); + +if (removed) +xenbus_switch_state (front_info->xb_dev, XenbusStateInitialising); +else +xenbus_switch_state (front_info->xb_dev, XenbusStateReconfiguring); } static void backend_on_changed(struct xenbus_device *xb_dev,@@ -148,6 +310,7 @@ static int xen_drv_probe(struct xenbus_device *xb_dev, front_info->xb_dev = xb_dev;spin_lock_init (&front_info->io_lock); + front_info->drm_pdrv_registered = false;dev_set_drvdata (&xb_dev->dev, front_info);return xenbus_switch_state (xb_dev, XenbusStateInitialising); }drivers/gpu/drm/xen/xen_drm_front.h +24
-0@@ -19,6 +19,8 @@#ifndef __XEN_DRM_FRONT_H_#define __XEN_DRM_FRONT_H_ +#include <linux/scatterlist.h> +#include "xen_drm_front_cfg.h" #ifndef GRANT_INVALID_REF @@ -30,16 +32,38 @@#define GRANT_INVALID_REF 0#endif +struct xen_drm_front_drm_pipeline ; +struct xen_drm_front_ops { +int (*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); +int (*dbuf_create_from_pages)(struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct page **pages); +int (*dbuf_create_from_sgt)(struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct sg_table *sgt); +int (*dbuf_destroy)(struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie); +int (*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); +int (*fb_detach)(struct xen_drm_front_info *front_info, +uint64_t fb_cookie); +int (*page_flip)(struct xen_drm_front_info *front_info, +int conn_idx,uint64_t fb_cookie);/* CAUTION! this is called with a spin_lock held! */ void (*on_frame_done)(struct platform_device *pdev,int conn_idx,uint64_t fb_cookie); +void (*drm_last_close)(struct xen_drm_front_info *front_info); };struct xen_drm_front_info {struct xenbus_device *xb_dev;/* to protect data between backend IO code and interrupt handler */ spinlock_t io_lock; +bool drm_pdrv_registered;/* virtual DRM platform device */ struct platform_device *drm_pdev;drivers/gpu/drm/xen/xen_drm_front_drv.c new file +211
-0@@ -0,0 +1,211 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include <drm/drmP.h> +#include <drm/drm_gem.h> +#include <drm/drm_atomic_helper.h> + +#include "xen_drm_front.h" +#include "xen_drm_front_cfg.h" +#include "xen_drm_front_drv.h" + +static int dumb_create (struct drm_file *filp, +struct drm_device *dev,struct drm_mode_create_dumb *args) +{ +return -EINVAL ; +} + +static void free_object (struct drm_gem_object *obj) +{ +struct xen_drm_front_drm_info *drm_info = obj->dev->dev_private; + + drm_info->front_ops->dbuf_destroy (drm_info->front_info, +xen_drm_front_dbuf_to_cookie (obj)); +} + +static void on_frame_done (struct platform_device *pdev, +int conn_idx,uint64_t fb_cookie) +{ +} + +static void lastclose (struct drm_device *dev) +{ +struct xen_drm_front_drm_info *drm_info = dev->dev_private; + + drm_info->front_ops->drm_last_close (drm_info->front_info); +} + +static int gem_mmap (struct file *filp,struct vm_area_struct *vma) +{ +return -EINVAL ; +} + +static struct sg_table *prime_get_sg_table (struct drm_gem_object *obj) +{ +return NULL ; +} + +static struct drm_gem_object *prime_import_sg_table (struct drm_device *dev, +struct dma_buf_attachment *attach,struct sg_table *sgt) +{ +return NULL ; +} + +static void *prime_vmap (struct drm_gem_object *obj) +{ +return NULL ; +} + +static void prime_vunmap (struct drm_gem_object *obj,void *vaddr) +{ +} + +static int prime_mmap (struct drm_gem_object *obj,struct vm_area_struct *vma) +{ +return -EINVAL ; +} + +static const struct file_operations xendrm_fops = { + .owner =THIS_MODULE , + .open = drm_open, + .release = drm_release, + .unlocked_ioctl = drm_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif + .poll = drm_poll, + .read = drm_read, + .llseek = no_llseek, + .mmap = gem_mmap, +}; + +static const struct vm_operations_struct xen_drm_vm_ops = { + .open = drm_gem_vm_open, + .close = drm_gem_vm_close, +}; + +struct drm_driver xen_drm_driver = { + .driver_features =DRIVER_GEM |DRIVER_MODESET | +DRIVER_PRIME |DRIVER_ATOMIC , + .lastclose = lastclose, + .gem_free_object_unlocked = free_object, + .gem_vm_ops = &xen_drm_vm_ops, + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, + .gem_prime_import = drm_gem_prime_import, + .gem_prime_export = drm_gem_prime_export, + .gem_prime_get_sg_table = prime_get_sg_table, + .gem_prime_import_sg_table = prime_import_sg_table, + .gem_prime_vmap = prime_vmap, + .gem_prime_vunmap = prime_vunmap, + .gem_prime_mmap = prime_mmap, + .dumb_create = dumb_create, + .fops = &xendrm_fops, + .name ="xendrm-du" , + .desc ="Xen PV DRM Display Unit" , + .date ="20161109" , + .major =1 , + .minor =0 , +}; + +int xen_drm_front_drv_probe (struct platform_device *pdev, +struct xen_drm_front_ops *front_ops) +{ +struct xen_drm_front_cfg *cfg =dev_get_platdata (&pdev->dev); +struct xen_drm_front_drm_info *drm_info; +struct drm_device *dev; +int ret; + +DRM_INFO ("Creating %s\n" , xen_drm_driver.desc); + + drm_info =devm_kzalloc (&pdev->dev,sizeof (*drm_info),GFP_KERNEL ); +if (!drm_info) +return -ENOMEM ; + + drm_info->front_ops = front_ops; + drm_info->front_ops->on_frame_done = on_frame_done; + drm_info->front_info = cfg->front_info; + + dev =drm_dev_alloc (&xen_drm_driver, &pdev->dev); +if (!dev) +return -ENOMEM ; + + drm_info->drm_dev = dev; + + drm_info->cfg = cfg; + dev->dev_private = drm_info; +platform_set_drvdata (pdev, drm_info); + + ret =drm_vblank_init (dev, cfg->num_connectors); +if (ret) { +DRM_ERROR ("Failed to initialize vblank, ret %d\n" , ret); +return ret; + } + + dev->irq_enabled =1 ; + + ret =drm_dev_register (dev,0 ); +if (ret) + goto fail_register; + +DRM_INFO ("Initialized %s %d.%d.%d %s on minor %d\n" , + xen_drm_driver.name, xen_drm_driver.major, + xen_drm_driver.minor, xen_drm_driver.patchlevel, + xen_drm_driver.date, dev->primary->index); + +return 0 ; + +fail_register: +drm_dev_unregister (dev); +drm_mode_config_cleanup (dev); +return ret; +} + +int xen_drm_front_drv_remove (struct platform_device *pdev) +{ +struct xen_drm_front_drm_info *drm_info =platform_get_drvdata (pdev); +struct drm_device *dev = drm_info->drm_dev; + +if (dev) { +drm_dev_unregister (dev); +drm_atomic_helper_shutdown (dev); +drm_mode_config_cleanup (dev); +drm_dev_unref (dev); + } +return 0 ; +} + +bool xen_drm_front_drv_is_used (struct platform_device *pdev) +{ +struct xen_drm_front_drm_info *drm_info =platform_get_drvdata (pdev); +struct drm_device *dev; + +if (!drm_info) +return false; + + dev = drm_info->drm_dev; +if (!dev) +return false; + +/* +* FIXME: the code below must be protected by drm_global_mutex, +* but it is not accessible to us. Anyways there is a race condition, +* but we will re-try. +*/ +return dev->open_count !=0 ; +}drivers/gpu/drm/xen/xen_drm_front_drv.h new file +60
-0@@ -0,0 +1,60 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_DRV_H_ +#define __XEN_DRM_FRONT_DRV_H_ + +#include <drm/drmP.h> + +#include "xen_drm_front.h" +#include "xen_drm_front_cfg.h" + +struct xen_drm_front_drm_pipeline { +struct xen_drm_front_drm_info *drm_info; + +int index; +}; + +struct xen_drm_front_drm_info { +struct xen_drm_front_info *front_info; +struct xen_drm_front_ops *front_ops; +struct drm_device *drm_dev; +struct xen_drm_front_cfg *cfg; +}; + +static inline uint64_t xen_drm_front_fb_to_cookie ( +struct drm_framebuffer *fb) +{ +return (uint64_t )fb; +} + +static inline uint64_t xen_drm_front_dbuf_to_cookie ( +struct drm_gem_object *gem_obj) +{ +return (uint64_t )gem_obj; +} + +int xen_drm_front_drv_probe (struct platform_device *pdev, +struct xen_drm_front_ops *front_ops); + +int xen_drm_front_drv_remove (struct platform_device *pdev); + +bool xen_drm_front_drv_is_used (struct platform_device *pdev); + +#endif /* __XEN_DRM_FRONT_DRV_H_ */ +Signature · 1 line
2.7.4
Quoted 4 lines
Quoted 4 lines
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Re: [PATCH 6/9] drm/xen-front: Introduce DRM/KMS virtual display driver
In reply to Oleksandr AndrushchenkoQuoted 122 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Implement essential initialization of the display driver:
- introduce required data structures
- handle DRM/KMS driver registration
- perform basic DRM driver initialization
- register driver on backend connection
- remove driver on backend disconnect
- introduce essential callbacks required by DRM/KMS core
- introduce essential callbacks required for frontend operationsSigned-off-by Oleksandr Andrushchenko <[email protected]>--- drivers/gpu/drm/xen/Makefile | 1 + drivers/gpu/drm/xen/xen_drm_front.c | 169 ++++++++++++++++++++++++- drivers/gpu/drm/xen/xen_drm_front.h | 24 ++++ drivers/gpu/drm/xen/xen_drm_front_drv.c | 211 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_drv.h | 60 +++++++++ 5 files changed, 462 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/xen/xen_drm_front_drv.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_drv.hdrivers/gpu/drm/xen/Makefile +1
-0@@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 drm_xen_front-objs := xen_drm_front.o \ + xen_drm_front_drv.o \ xen_drm_front_evtchnl.o \ xen_drm_front_shbuf.o \ xen_drm_front_cfg.odrivers/gpu/drm/xen/xen_drm_front.c +69
-0@@ -18,6 +18,8 @@#include <drm/drmP.h> +#include <linux/of_device.h> +#include <xen/platform_pci.h> #include <xen/xen.h> #include <xen/xenbus.h> @@ -25,15 +27,161 @@#include <xen/interface/io/displif.h> #include "xen_drm_front.h" +#include "xen_drm_front_drv.h" #include "xen_drm_front_evtchnl.h" #include "xen_drm_front_shbuf.h" +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 ; +} + +static int be_dbuf_create_int (struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct page **pages, +struct sg_table *sgt) +{ +return 0 ; +} + +static int be_dbuf_create_from_sgt (struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct sg_table *sgt) +{ +return be_dbuf_create_int (front_info, dbuf_cookie, width, height, + bpp, size,NULL , sgt); +} + +static int be_dbuf_create_from_pages (struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct page **pages) +{ +return be_dbuf_create_int (front_info, dbuf_cookie, width, height, + bpp, size, pages,NULL ); +} + +static int be_dbuf_destroy (struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie) +{ +return 0 ; +} + +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 ; +} + +static int be_fb_detach (struct xen_drm_front_info *front_info, +uint64_t fb_cookie) +{ +return 0 ; +} + +static int be_page_flip (struct xen_drm_front_info *front_info,int conn_idx, +uint64_t fb_cookie) +{ +return 0 ; +} + +static void xen_drm_drv_unload (struct xen_drm_front_info *front_info) +{ +if (front_info->xb_dev->state != XenbusStateReconfiguring) +return ; + +DRM_DEBUG ("Can try removing driver now\n" ); +xenbus_switch_state (front_info->xb_dev, XenbusStateInitialising); +} +static struct xen_drm_front_ops front_ops = {
drivers/gpu/drm/xen/xen_drm_front.c line 109
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front.c +9
-1-/* placeholder for now */ + .mode_set = be_mode_set, + .dbuf_create_from_pages = be_dbuf_create_from_pages, + .dbuf_create_from_sgt = be_dbuf_create_from_sgt, + .dbuf_destroy = be_dbuf_destroy, + .fb_attach = be_fb_attach, + .fb_detach = be_fb_detach, + .page_flip = be_page_flip, + .drm_last_close = xen_drm_drv_unload, +};
This looks like a midlayer/DRM-abstraction in your driver. Please remove, and instead directly hook your xen-front code into the relevant drm callbacks.
In general also pls make sure you don't implement dummy callbacks that do nothing, we've tried really hard to make them all optional in the drm infrastructure.
-Daniel
Quoted 458 lines
drivers/gpu/drm/xen/xen_drm_front.c +88
-2+ +static int xen_drm_drv_probe (struct platform_device *pdev) +{ +/* +* The device is not spawn from a device tree, so arch_setup_dma_ops +* is not called, thus leaving the device with dummy DMA ops. +* This makes the device return error on PRIME buffer import, which +* is not correct: to fix this call of_dma_configure() with a NULL +* node to set default DMA ops. +*/ +of_dma_configure (&pdev->dev,NULL ); +return xen_drm_front_drv_probe (pdev, &front_ops); +} + +static int xen_drm_drv_remove (struct platform_device *pdev) +{ +return xen_drm_front_drv_remove (pdev); +} + +struct platform_device_info xen_drm_front_platform_info = { + .name =XENDISPL_DRIVER_NAME , + .id =0 , + .num_res =0 , + .dma_mask =DMA_BIT_MASK (32 ), }; +static struct platform_driver xen_drm_front_front_info = { + .probe = xen_drm_drv_probe, + .remove = xen_drm_drv_remove, + .driver = { + .name =XENDISPL_DRIVER_NAME , + }, +}; + +static void xen_drm_drv_deinit (struct xen_drm_front_info *front_info) +{ +if (!front_info->drm_pdrv_registered) +return ; + +if (front_info->drm_pdev) +platform_device_unregister (front_info->drm_pdev); + +platform_driver_unregister (&xen_drm_front_front_info); + front_info->drm_pdrv_registered = false; + front_info->drm_pdev =NULL ; +} + +static int xen_drm_drv_init (struct xen_drm_front_info *front_info) +{ +int ret; + + ret =platform_driver_register (&xen_drm_front_front_info); +if (ret <0 ) +return ret; + + front_info->drm_pdrv_registered = true; +/* pass card configuration via platform data */ + xen_drm_front_platform_info.data = &front_info->cfg; + xen_drm_front_platform_info.size_data =sizeof (front_info->cfg); + + front_info->drm_pdev =platform_device_register_full ( + &xen_drm_front_platform_info); +if (IS_ERR_OR_NULL (front_info->drm_pdev)) { +DRM_ERROR ("Failed to register " XENDISPL_DRIVER_NAME " PV DRM driver\n" ); + front_info->drm_pdev =NULL ; +xen_drm_drv_deinit (front_info); +return -ENODEV ; + } + +return 0 ; +} +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); }@@ -59,13 +207,27 @@ static int backend_on_initwait(struct xen_drm_front_info *front_info)static int backend_on_connected (struct xen_drm_front_info *front_info) {xen_drm_front_evtchnl_set_state (front_info,EVTCHNL_STATE_CONNECTED ); -return 0 ; +return xen_drm_drv_init (front_info); }static void backend_on_disconnected (struct xen_drm_front_info *front_info) { +bool removed = true; + +if (front_info->drm_pdev) { +if (xen_drm_front_drv_is_used (front_info->drm_pdev)) { +DRM_WARN ("DRM driver still in use, deferring removal\n" ); + removed = false; + }else +xen_drv_remove_internal (front_info); + } +xen_drm_front_evtchnl_set_state (front_info,EVTCHNL_STATE_DISCONNECTED ); -xenbus_switch_state (front_info->xb_dev, XenbusStateInitialising); + +if (removed) +xenbus_switch_state (front_info->xb_dev, XenbusStateInitialising); +else +xenbus_switch_state (front_info->xb_dev, XenbusStateReconfiguring); } static void backend_on_changed(struct xenbus_device *xb_dev,@@ -148,6 +310,7 @@ static int xen_drv_probe(struct xenbus_device *xb_dev, front_info->xb_dev = xb_dev;spin_lock_init (&front_info->io_lock); + front_info->drm_pdrv_registered = false;dev_set_drvdata (&xb_dev->dev, front_info);return xenbus_switch_state (xb_dev, XenbusStateInitialising); }drivers/gpu/drm/xen/xen_drm_front.h +24
-0@@ -19,6 +19,8 @@#ifndef __XEN_DRM_FRONT_H_#define __XEN_DRM_FRONT_H_ +#include <linux/scatterlist.h> +#include "xen_drm_front_cfg.h" #ifndef GRANT_INVALID_REF @@ -30,16 +32,38 @@#define GRANT_INVALID_REF 0#endif +struct xen_drm_front_drm_pipeline ; +struct xen_drm_front_ops { +int (*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); +int (*dbuf_create_from_pages)(struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct page **pages); +int (*dbuf_create_from_sgt)(struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct sg_table *sgt); +int (*dbuf_destroy)(struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie); +int (*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); +int (*fb_detach)(struct xen_drm_front_info *front_info, +uint64_t fb_cookie); +int (*page_flip)(struct xen_drm_front_info *front_info, +int conn_idx,uint64_t fb_cookie);/* CAUTION! this is called with a spin_lock held! */ void (*on_frame_done)(struct platform_device *pdev,int conn_idx,uint64_t fb_cookie); +void (*drm_last_close)(struct xen_drm_front_info *front_info); };struct xen_drm_front_info {struct xenbus_device *xb_dev;/* to protect data between backend IO code and interrupt handler */ spinlock_t io_lock; +bool drm_pdrv_registered;/* virtual DRM platform device */ struct platform_device *drm_pdev;drivers/gpu/drm/xen/xen_drm_front_drv.c new file +211
-0@@ -0,0 +1,211 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include <drm/drmP.h> +#include <drm/drm_gem.h> +#include <drm/drm_atomic_helper.h> + +#include "xen_drm_front.h" +#include "xen_drm_front_cfg.h" +#include "xen_drm_front_drv.h" + +static int dumb_create (struct drm_file *filp, +struct drm_device *dev,struct drm_mode_create_dumb *args) +{ +return -EINVAL ; +} + +static void free_object (struct drm_gem_object *obj) +{ +struct xen_drm_front_drm_info *drm_info = obj->dev->dev_private; + + drm_info->front_ops->dbuf_destroy (drm_info->front_info, +xen_drm_front_dbuf_to_cookie (obj)); +} + +static void on_frame_done (struct platform_device *pdev, +int conn_idx,uint64_t fb_cookie) +{ +} + +static void lastclose (struct drm_device *dev) +{ +struct xen_drm_front_drm_info *drm_info = dev->dev_private; + + drm_info->front_ops->drm_last_close (drm_info->front_info); +} + +static int gem_mmap (struct file *filp,struct vm_area_struct *vma) +{ +return -EINVAL ; +} + +static struct sg_table *prime_get_sg_table (struct drm_gem_object *obj) +{ +return NULL ; +} + +static struct drm_gem_object *prime_import_sg_table (struct drm_device *dev, +struct dma_buf_attachment *attach,struct sg_table *sgt) +{ +return NULL ; +} + +static void *prime_vmap (struct drm_gem_object *obj) +{ +return NULL ; +} + +static void prime_vunmap (struct drm_gem_object *obj,void *vaddr) +{ +} + +static int prime_mmap (struct drm_gem_object *obj,struct vm_area_struct *vma) +{ +return -EINVAL ; +} + +static const struct file_operations xendrm_fops = { + .owner =THIS_MODULE , + .open = drm_open, + .release = drm_release, + .unlocked_ioctl = drm_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = drm_compat_ioctl, +#endif + .poll = drm_poll, + .read = drm_read, + .llseek = no_llseek, + .mmap = gem_mmap, +}; + +static const struct vm_operations_struct xen_drm_vm_ops = { + .open = drm_gem_vm_open, + .close = drm_gem_vm_close, +}; + +struct drm_driver xen_drm_driver = { + .driver_features =DRIVER_GEM |DRIVER_MODESET | +DRIVER_PRIME |DRIVER_ATOMIC , + .lastclose = lastclose, + .gem_free_object_unlocked = free_object, + .gem_vm_ops = &xen_drm_vm_ops, + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, + .gem_prime_import = drm_gem_prime_import, + .gem_prime_export = drm_gem_prime_export, + .gem_prime_get_sg_table = prime_get_sg_table, + .gem_prime_import_sg_table = prime_import_sg_table, + .gem_prime_vmap = prime_vmap, + .gem_prime_vunmap = prime_vunmap, + .gem_prime_mmap = prime_mmap, + .dumb_create = dumb_create, + .fops = &xendrm_fops, + .name ="xendrm-du" , + .desc ="Xen PV DRM Display Unit" , + .date ="20161109" , + .major =1 , + .minor =0 , +}; + +int xen_drm_front_drv_probe (struct platform_device *pdev, +struct xen_drm_front_ops *front_ops) +{ +struct xen_drm_front_cfg *cfg =dev_get_platdata (&pdev->dev); +struct xen_drm_front_drm_info *drm_info; +struct drm_device *dev; +int ret; + +DRM_INFO ("Creating %s\n" , xen_drm_driver.desc); + + drm_info =devm_kzalloc (&pdev->dev,sizeof (*drm_info),GFP_KERNEL ); +if (!drm_info) +return -ENOMEM ; + + drm_info->front_ops = front_ops; + drm_info->front_ops->on_frame_done = on_frame_done; + drm_info->front_info = cfg->front_info; + + dev =drm_dev_alloc (&xen_drm_driver, &pdev->dev); +if (!dev) +return -ENOMEM ; + + drm_info->drm_dev = dev; + + drm_info->cfg = cfg; + dev->dev_private = drm_info; +platform_set_drvdata (pdev, drm_info); + + ret =drm_vblank_init (dev, cfg->num_connectors); +if (ret) { +DRM_ERROR ("Failed to initialize vblank, ret %d\n" , ret); +return ret; + } + + dev->irq_enabled =1 ; + + ret =drm_dev_register (dev,0 ); +if (ret) + goto fail_register; + +DRM_INFO ("Initialized %s %d.%d.%d %s on minor %d\n" , + xen_drm_driver.name, xen_drm_driver.major, + xen_drm_driver.minor, xen_drm_driver.patchlevel, + xen_drm_driver.date, dev->primary->index); + +return 0 ; + +fail_register: +drm_dev_unregister (dev); +drm_mode_config_cleanup (dev); +return ret; +} + +int xen_drm_front_drv_remove (struct platform_device *pdev) +{ +struct xen_drm_front_drm_info *drm_info =platform_get_drvdata (pdev); +struct drm_device *dev = drm_info->drm_dev; + +if (dev) { +drm_dev_unregister (dev); +drm_atomic_helper_shutdown (dev); +drm_mode_config_cleanup (dev); +drm_dev_unref (dev); + } +return 0 ; +} + +bool xen_drm_front_drv_is_used (struct platform_device *pdev) +{ +struct xen_drm_front_drm_info *drm_info =platform_get_drvdata (pdev); +struct drm_device *dev; + +if (!drm_info) +return false; + + dev = drm_info->drm_dev; +if (!dev) +return false; + +/* +* FIXME: the code below must be protected by drm_global_mutex, +* but it is not accessible to us. Anyways there is a race condition, +* but we will re-try. +*/ +return dev->open_count !=0 ; +}drivers/gpu/drm/xen/xen_drm_front_drv.h new file +60
-0@@ -0,0 +1,60 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_DRV_H_ +#define __XEN_DRM_FRONT_DRV_H_ + +#include <drm/drmP.h> + +#include "xen_drm_front.h" +#include "xen_drm_front_cfg.h" + +struct xen_drm_front_drm_pipeline { +struct xen_drm_front_drm_info *drm_info; + +int index; +}; + +struct xen_drm_front_drm_info { +struct xen_drm_front_info *front_info; +struct xen_drm_front_ops *front_ops; +struct drm_device *drm_dev; +struct xen_drm_front_cfg *cfg; +}; + +static inline uint64_t xen_drm_front_fb_to_cookie ( +struct drm_framebuffer *fb) +{ +return (uint64_t )fb; +} + +static inline uint64_t xen_drm_front_dbuf_to_cookie ( +struct drm_gem_object *gem_obj) +{ +return (uint64_t )gem_obj; +} + +int xen_drm_front_drv_probe (struct platform_device *pdev, +struct xen_drm_front_ops *front_ops); + +int xen_drm_front_drv_remove (struct platform_device *pdev); + +bool xen_drm_front_drv_is_used (struct platform_device *pdev); + +#endif /* __XEN_DRM_FRONT_DRV_H_ */ +Signature · 6 lines
2.7.4 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Signature · 8 lines
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ Xen-devel mailing list [email protected] https://lists.xenproject.org/mailman/listinfo/xen-devel
PATCH 6/9 drm/xen-front: Introduce DRM/KMS virtual display driver
In reply to Oleksandr AndrushchenkoFrom: Oleksandr Andrushchenko <[email protected]>
Implement essential initialization of the display driver:
- introduce required data structures
- handle DRM/KMS driver registration
- perform basic DRM driver initialization
- register driver on backend connection
- remove driver on backend disconnect
- introduce essential callbacks required by DRM/KMS core
- introduce essential callbacks required for frontend operations
--- drivers/gpu/drm/xen/Makefile | 1 + drivers/gpu/drm/xen/xen_drm_front.c | 169 ++++++++++++++++++++++++- drivers/gpu/drm/xen/xen_drm_front.h | 24 ++++ drivers/gpu/drm/xen/xen_drm_front_drv.c | 211 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_drv.h | 60 +++++++++ 5 files changed, 462 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/xen/xen_drm_front_drv.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_drv.h
drivers/gpu/drm/xen/Makefile +1 -0
@@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 drm_xen_front-objs := xen_drm_front.o \ + xen_drm_front_drv.o \ xen_drm_front_evtchnl.o \ xen_drm_front_shbuf.o \ xen_drm_front_cfg.o
drivers/gpu/drm/xen/xen_drm_front.c +166 -3
206 lines not on this page · raw message
drivers/gpu/drm/xen/xen_drm_front.h +24 -0
@@ -19,6 +19,8 @@#ifndef __XEN_DRM_FRONT_H_#define __XEN_DRM_FRONT_H_ +#include <linux/scatterlist.h> +#include "xen_drm_front_cfg.h" #ifndef GRANT_INVALID_REF
@@ -30,16 +32,38 @@#define GRANT_INVALID_REF 0#endif +struct xen_drm_front_drm_pipeline ; +struct xen_drm_front_ops { +int (*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); +int (*dbuf_create_from_pages)(struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct page **pages); +int (*dbuf_create_from_sgt)(struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie,uint32_t width,uint32_t height, +uint32_t bpp,uint64_t size,struct sg_table *sgt); +int (*dbuf_destroy)(struct xen_drm_front_info *front_info, +uint64_t dbuf_cookie); +int (*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); +int (*fb_detach)(struct xen_drm_front_info *front_info, +uint64_t fb_cookie); +int (*page_flip)(struct xen_drm_front_info *front_info, +int conn_idx,uint64_t fb_cookie);/* CAUTION! this is called with a spin_lock held! */ void (*on_frame_done)(struct platform_device *pdev,int conn_idx,uint64_t fb_cookie); +void (*drm_last_close)(struct xen_drm_front_info *front_info); };struct xen_drm_front_info {struct xenbus_device *xb_dev;/* to protect data between backend IO code and interrupt handler */ spinlock_t io_lock; +bool drm_pdrv_registered;/* virtual DRM platform device */ struct platform_device *drm_pdev;
drivers/gpu/drm/xen/xen_drm_front_drv.c new file +211 -0
211 lines not on this page · raw message
drivers/gpu/drm/xen/xen_drm_front_drv.h new file +60 -0
60 lines not on this page · raw message
Signature · 7 lines
2.7.4 _______________________________________________ Xen-devel mailing list [email protected] https://lists.xenproject.org/mailman/listinfo/xen-devel
PATCH 7/9 drm/xen-front: Implement KMS/connector handling
In reply to Oleksandr AndrushchenkoFrom: Oleksandr Andrushchenko <[email protected]>
Implement kernel modesetiing/connector handling using DRM simple KMS helper pipeline:
- implement KMS part of the driver with the help of DRM simple pipepline helper which is possible due to the fact that the para-virtualized driver only supports a single (primary) plane:
- initialize connectors according to XenStore configuration
- handle frame done events from the backend
- generate vblank events
- create and destroy frame buffers and propagate those to the backend
- propagate set/reset mode configuration to the backend on display enable/disable callbacks
- send page flip request to the backend and implement logic for reporting backend IO errors on prepare fb callback
- implement virtual connector handling:
- support only pixel formats suitable for single plane modes
- make sure the connector is always connected
- support a single video mode as per para-virtualized driver configuration
--- drivers/gpu/drm/xen/Makefile | 2 + drivers/gpu/drm/xen/xen_drm_front_conn.c | 125 +++++++++++++ drivers/gpu/drm/xen/xen_drm_front_conn.h | 35 ++++ drivers/gpu/drm/xen/xen_drm_front_drv.c | 15 ++ drivers/gpu/drm/xen/xen_drm_front_drv.h | 12 ++ drivers/gpu/drm/xen/xen_drm_front_kms.c | 299 +++++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_kms.h | 30 ++++ 7 files changed, 518 insertions(+) create mode 100644 drivers/gpu/drm/xen/xen_drm_front_conn.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_conn.h create mode 100644 drivers/gpu/drm/xen/xen_drm_front_kms.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_kms.h
drivers/gpu/drm/xen/Makefile +2 -0
@@ -2,6 +2,8 @@ drm_xen_front-objs := xen_drm_front.o \ xen_drm_front_drv.o \ + xen_drm_front_kms.o \ + xen_drm_front_conn.o \ xen_drm_front_evtchnl.o \ xen_drm_front_shbuf.o \ xen_drm_front_cfg.o
drivers/gpu/drm/xen/xen_drm_front_conn.c new file +125 -0
125 lines not on this page · raw message
drivers/gpu/drm/xen/xen_drm_front_conn.h new file +35 -0
@@ -0,0 +1,35 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_CONN_H_ +#define __XEN_DRM_FRONT_CONN_H_ + +#include <drm/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_encoder.h> + +#include <linux/wait.h> + +struct xen_drm_front_drm_info ; + +const uint32_t *xen_drm_front_conn_get_formats (int *format_count); + +int xen_drm_front_conn_init (struct xen_drm_front_drm_info *drm_info, +struct drm_connector *connector); + +#endif /* __XEN_DRM_FRONT_CONN_H_ */
drivers/gpu/drm/xen/xen_drm_front_drv.c +15 -0
@@ -23,6 +23,7 @@#include "xen_drm_front.h" #include "xen_drm_front_cfg.h" #include "xen_drm_front_drv.h" +#include "xen_drm_front_kms.h" static int dumb_create (struct drm_file *filp,struct drm_device *dev,struct drm_mode_create_dumb *args)
@@ -41,6 +42,13 @@ static void free_object(struct drm_gem_object *obj)static void on_frame_done (struct platform_device *pdev,int conn_idx,uint64_t fb_cookie) { +struct xen_drm_front_drm_info *drm_info =platform_get_drvdata (pdev); + +if (unlikely (conn_idx >= drm_info->cfg->num_connectors)) +return ; + +xen_drm_front_kms_on_frame_done (&drm_info->pipeline[conn_idx], + fb_cookie); }static void lastclose (struct drm_device *dev)
@@ -157,6 +165,12 @@ int xen_drm_front_drv_probe(struct platform_device *pdev,return ret; } + ret =xen_drm_front_kms_init (drm_info); +if (ret) { +DRM_ERROR ("Failed to initialize DRM/KMS, ret %d\n" , ret); + goto fail_modeset; + } + dev->irq_enabled =1 ; ret =drm_dev_register (dev,0 );
@@ -172,6 +186,7 @@ int xen_drm_front_drv_probe(struct platform_device *pdev, fail_register:drm_dev_unregister (dev); +fail_modeset:drm_mode_config_cleanup (dev);return ret; }
drivers/gpu/drm/xen/xen_drm_front_drv.h +12 -0
@@ -20,14 +20,24 @@#define __XEN_DRM_FRONT_DRV_H_#include <drm/drmP.h> +#include <drm/drm_simple_kms_helper.h> #include "xen_drm_front.h" #include "xen_drm_front_cfg.h" +#include "xen_drm_front_conn.h" struct xen_drm_front_drm_pipeline {struct xen_drm_front_drm_info *drm_info;int index; + +struct drm_simple_display_pipe pipe; + +struct drm_connector conn; +/* these are only for connector mode checking */ +int width, height; +/* last backend error seen on page flip */ +int pgflip_last_error; };struct xen_drm_front_drm_info {
@@ -35,6 +45,8 @@ struct xen_drm_front_drm_info {struct xen_drm_front_ops *front_ops;struct drm_device *drm_dev;struct xen_drm_front_cfg *cfg; + +struct xen_drm_front_drm_pipeline pipeline[XEN_DRM_FRONT_MAX_CRTCS ]; }; static inline uint64_t xen_drm_front_fb_to_cookie(
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +299 -0
299 lines not on this page · raw message
drivers/gpu/drm/xen/xen_drm_front_kms.h new file +30 -0
@@ -0,0 +1,30 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_KMS_H_ +#define __XEN_DRM_FRONT_KMS_H_ + +#include "xen_drm_front_drv.h" + +int xen_drm_front_kms_init (struct xen_drm_front_drm_info *drm_info); + +void xen_drm_front_kms_on_frame_done ( +struct xen_drm_front_drm_pipeline *pipeline, +uint64_t fb_cookie); + +#endif /* __XEN_DRM_FRONT_KMS_H_ */
Signature · 6 lines
2.7.4 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 7/9] drm/xen-front: Implement KMS/connector handling
Quoted 19 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Implement kernel modesetiing/connector handling using DRM simple KMS helper pipeline:
- implement KMS part of the driver with the help of DRM simple pipepline helper which is possible due to the fact that the para-virtualized driver only supports a single (primary) plane:
- initialize connectors according to XenStore configuration
- handle frame done events from the backend
- generate vblank events
- create and destroy frame buffers and propagate those to the backend
- propagate set/reset mode configuration to the backend on display enable/disable callbacks
- send page flip request to the backend and implement logic for reporting backend IO errors on prepare fb callback
Quoted 7 lines
- implement virtual connector handling:
- support only pixel formats suitable for single plane modes
- make sure the connector is always connected
- support a single video mode as per para-virtualized driver configurationSigned-off-by Oleksandr Andrushchenko <[email protected]>
I think once you've removed the midlayer in the previous patch it would makes sense to merge the 2 patches into 1.
Bunch more comments below.
-Daniel
Quoted 391 lines
--- drivers/gpu/drm/xen/Makefile | 2 + drivers/gpu/drm/xen/xen_drm_front_conn.c | 125 +++++++++++++ drivers/gpu/drm/xen/xen_drm_front_conn.h | 35 ++++ drivers/gpu/drm/xen/xen_drm_front_drv.c | 15 ++ drivers/gpu/drm/xen/xen_drm_front_drv.h | 12 ++ drivers/gpu/drm/xen/xen_drm_front_kms.c | 299 +++++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_kms.h | 30 ++++ 7 files changed, 518 insertions(+) create mode 100644 drivers/gpu/drm/xen/xen_drm_front_conn.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_conn.h create mode 100644 drivers/gpu/drm/xen/xen_drm_front_kms.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_kms.hdrivers/gpu/drm/xen/Makefile +2
-0@@ -2,6 +2,8 @@ drm_xen_front-objs := xen_drm_front.o \ xen_drm_front_drv.o \ + xen_drm_front_kms.o \ + xen_drm_front_conn.o \ xen_drm_front_evtchnl.o \ xen_drm_front_shbuf.o \ xen_drm_front_cfg.odrivers/gpu/drm/xen/xen_drm_front_conn.c new file +125
-0@@ -0,0 +1,125 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_crtc_helper.h> + +#include <video/videomode.h> + +#include "xen_drm_front_conn.h" +#include "xen_drm_front_drv.h" + +static struct xen_drm_front_drm_pipeline * +to_xen_drm_pipeline (struct drm_connector *connector) +{ + return container_of(connector, struct xen_drm_front_drm_pipeline, conn); +} + +static const uint32_t plane_formats[] = { +DRM_FORMAT_RGB565 , +DRM_FORMAT_RGB888 , +DRM_FORMAT_XRGB8888 , +DRM_FORMAT_ARGB8888 , +DRM_FORMAT_XRGB4444 , +DRM_FORMAT_ARGB4444 , +DRM_FORMAT_XRGB1555 , +DRM_FORMAT_ARGB1555 , +}; + +const uint32_t *xen_drm_front_conn_get_formats (int *format_count) +{ + *format_count =ARRAY_SIZE (plane_formats); +return plane_formats; +} + +static enum drm_connector_status connector_detect ( +struct drm_connector *connector,bool force) +{ +if (drm_dev_is_unplugged (connector->dev)) +return connector_status_disconnected; + +return connector_status_connected; +} + +#define XEN_DRM_NUM_VIDEO_MODES 1 +#define XEN_DRM_CRTC_VREFRESH_HZ 60 + +static int connector_get_modes (struct drm_connector *connector) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (connector); +struct drm_display_mode *mode; +struct videomode videomode; +int width, height; + + mode =drm_mode_create (connector->dev); +if (!mode) +return 0 ; + +memset (&videomode,0 ,sizeof (videomode)); + videomode.hactive = pipeline->width; + videomode.vactive = pipeline->height; + width = videomode.hactive + videomode.hfront_porch + + videomode.hback_porch + videomode.hsync_len; + height = videomode.vactive + videomode.vfront_porch + + videomode.vback_porch + videomode.vsync_len; + videomode.pixelclock = width * height *XEN_DRM_CRTC_VREFRESH_HZ ; + mode->type =DRM_MODE_TYPE_PREFERRED |DRM_MODE_TYPE_DRIVER ; + +drm_display_mode_from_videomode (&videomode, mode); +drm_mode_probed_add (connector, mode); +return XEN_DRM_NUM_VIDEO_MODES ; +} + +static int connector_mode_valid (struct drm_connector *connector, +struct drm_display_mode *mode) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (connector); + +if (mode->hdisplay != pipeline->width) +return MODE_ERROR ; + +if (mode->vdisplay != pipeline->height) +return MODE_ERROR ; + +return MODE_OK ; +} + +static const struct drm_connector_helper_funcs connector_helper_funcs = { + .get_modes = connector_get_modes, + .mode_valid = connector_mode_valid, +}; + +static const struct drm_connector_funcs connector_funcs = { + .detect = connector_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +int xen_drm_front_conn_init (struct xen_drm_front_drm_info *drm_info, +struct drm_connector *connector) +{ +drm_connector_helper_add (connector, &connector_helper_funcs); + +return drm_connector_init (drm_info->drm_dev, connector, + &connector_funcs,DRM_MODE_CONNECTOR_VIRTUAL ); +}drivers/gpu/drm/xen/xen_drm_front_conn.h new file +35
-0@@ -0,0 +1,35 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_CONN_H_ +#define __XEN_DRM_FRONT_CONN_H_ + +#include <drm/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_encoder.h> + +#include <linux/wait.h> + +struct xen_drm_front_drm_info ; + +const uint32_t *xen_drm_front_conn_get_formats (int *format_count); + +int xen_drm_front_conn_init (struct xen_drm_front_drm_info *drm_info, +struct drm_connector *connector); + +#endif /* __XEN_DRM_FRONT_CONN_H_ */ drivers/gpu/drm/xen/xen_drm_front_drv.c +15
-0@@ -23,6 +23,7 @@#include "xen_drm_front.h" #include "xen_drm_front_cfg.h" #include "xen_drm_front_drv.h" +#include "xen_drm_front_kms.h" static int dumb_create (struct drm_file *filp,struct drm_device *dev,struct drm_mode_create_dumb *args)@@ -41,6 +42,13 @@ static void free_object(struct drm_gem_object *obj)static void on_frame_done (struct platform_device *pdev,int conn_idx,uint64_t fb_cookie) { +struct xen_drm_front_drm_info *drm_info =platform_get_drvdata (pdev); + +if (unlikely (conn_idx >= drm_info->cfg->num_connectors)) +return ; + +xen_drm_front_kms_on_frame_done (&drm_info->pipeline[conn_idx], + fb_cookie); }static void lastclose (struct drm_device *dev)@@ -157,6 +165,12 @@ int xen_drm_front_drv_probe(struct platform_device *pdev,return ret; } + ret =xen_drm_front_kms_init (drm_info); +if (ret) { +DRM_ERROR ("Failed to initialize DRM/KMS, ret %d\n" , ret); + goto fail_modeset; + } + dev->irq_enabled =1 ; ret =drm_dev_register (dev,0 );@@ -172,6 +186,7 @@ int xen_drm_front_drv_probe(struct platform_device *pdev, fail_register:drm_dev_unregister (dev); +fail_modeset:drm_mode_config_cleanup (dev);return ret; }drivers/gpu/drm/xen/xen_drm_front_drv.h +12
-0@@ -20,14 +20,24 @@#define __XEN_DRM_FRONT_DRV_H_#include <drm/drmP.h> +#include <drm/drm_simple_kms_helper.h> #include "xen_drm_front.h" #include "xen_drm_front_cfg.h" +#include "xen_drm_front_conn.h" struct xen_drm_front_drm_pipeline {struct xen_drm_front_drm_info *drm_info;int index; + +struct drm_simple_display_pipe pipe; + +struct drm_connector conn; +/* these are only for connector mode checking */ +int width, height; +/* last backend error seen on page flip */ +int pgflip_last_error; };struct xen_drm_front_drm_info {@@ -35,6 +45,8 @@ struct xen_drm_front_drm_info {struct xen_drm_front_ops *front_ops;struct drm_device *drm_dev;struct xen_drm_front_cfg *cfg; + +struct xen_drm_front_drm_pipeline pipeline[XEN_DRM_FRONT_MAX_CRTCS ]; }; static inline uint64_t xen_drm_front_fb_to_cookie(drivers/gpu/drm/xen/xen_drm_front_kms.c new file +101
-0@@ -0,0 +1,299 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include "xen_drm_front_kms.h" + +#include <drm/drmP.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_gem.h> +#include <drm/drm_gem_framebuffer_helper.h> + +#include "xen_drm_front.h" +#include "xen_drm_front_conn.h" +#include "xen_drm_front_drv.h" + +static struct xen_drm_front_drm_pipeline * +to_xen_drm_pipeline (struct drm_simple_display_pipe *pipe) +{ + return container_of(pipe, struct xen_drm_front_drm_pipeline, pipe); +} + +static void fb_destroy (struct drm_framebuffer *fb) +{ +struct xen_drm_front_drm_info *drm_info = fb->dev->dev_private; + + drm_info->front_ops->fb_detach (drm_info->front_info, +xen_drm_front_fb_to_cookie (fb)); +drm_gem_fb_destroy (fb); +} + +static struct drm_framebuffer_funcs fb_funcs = { + .destroy = fb_destroy, +}; + +static struct drm_framebuffer *fb_create (struct drm_device *dev, +struct drm_file *filp,const struct drm_mode_fb_cmd2 *mode_cmd) +{ +struct xen_drm_front_drm_info *drm_info = dev->dev_private; +static struct drm_framebuffer *fb; +struct drm_gem_object *gem_obj; +int ret; + + fb =drm_gem_fb_create_with_funcs (dev, filp, mode_cmd, &fb_funcs); +if (IS_ERR_OR_NULL (fb)) +return fb; + + gem_obj =drm_gem_object_lookup (filp, mode_cmd->handles[0 ]); +if (!gem_obj) { +DRM_ERROR ("Failed to lookup GEM object\n" ); + ret = -ENOENT ; + goto fail; + } + +drm_gem_object_unreference_unlocked (gem_obj); + + ret = drm_info->front_ops->fb_attach ( + drm_info->front_info, +xen_drm_front_dbuf_to_cookie (gem_obj), +xen_drm_front_fb_to_cookie (fb), + fb->width, fb->height, fb->format->format); +if (ret <0 ) { +DRM_ERROR ("Back failed to attach FB %p: %d\n" , fb, ret); + goto fail; + } + +return fb; + +fail: +drm_gem_fb_destroy (fb); +return ERR_PTR (ret); +} + +static const struct drm_mode_config_funcs mode_config_funcs = { + .fb_create = fb_create, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +static int display_set_config (struct drm_simple_display_pipe *pipe, +struct drm_framebuffer *fb) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe); +struct drm_crtc *crtc = &pipe->crtc; +struct xen_drm_front_drm_info *drm_info = pipeline->drm_info; +int ret;
drivers/gpu/drm/xen/xen_drm_front_kms.c line 111
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +10
-0+ +if (fb) + ret = drm_info->front_ops->mode_set (pipeline, + crtc->x, crtc->y, + fb->width, fb->height, fb->format->cpp[0 ] *8 , +xen_drm_front_fb_to_cookie (fb)); +else + ret = drm_info->front_ops->mode_set (pipeline, +0 ,0 ,0 ,0 ,0 , +xen_drm_front_fb_to_cookie (NULL ));
This is a bit much layering, the if (fb) case corresponds to the display_enable/disable hooks, pls fold that in instead of the indirection. simple helpers guarantee that when the display is on, then you have an fb.
Maybe we need to fix the docs, pls check and if that's not clear, submit a kernel-doc patch for the simple pipe helpers.
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +5
-0+ +if (ret) +DRM_ERROR ("Failed to set mode to back: %d\n" , ret); + +return ret;
drivers/gpu/drm/xen/xen_drm_front_kms.c line 126
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +10
-0+} + +static void display_enable (struct drm_simple_display_pipe *pipe, +struct drm_crtc_state *crtc_state) +{ +struct drm_crtc *crtc = &pipe->crtc; +struct drm_framebuffer *fb = pipe->plane.state->fb; + +if (display_set_config (pipe, fb) ==0 ) +drm_crtc_vblank_on (crtc);
I get the impression your driver doesn't support vblanks (the page flip code at least looks like it's only generating a single event), you also don't have a enable/disable_vblank implementation. If there's no vblank handling then this shouldn't be needed.
Quoted 16 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +16
-0+else +DRM_ERROR ("Failed to enable display\n" ); +} + +static void display_disable (struct drm_simple_display_pipe *pipe) +{ +struct drm_crtc *crtc = &pipe->crtc; + +display_set_config (pipe,NULL ); +drm_crtc_vblank_off (crtc); +/* final check for stalled events */ +if (crtc->state->event && !crtc->state->active) { +unsigned long flags; + +spin_lock_irqsave (&crtc->dev->event_lock, flags); +drm_crtc_send_vblank_event (crtc, crtc->state->event);
drivers/gpu/drm/xen/xen_drm_front_kms.c line 152
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +10
-0+spin_unlock_irqrestore (&crtc->dev->event_lock, flags); + crtc->state->event =NULL ; + } +} + +void xen_drm_front_kms_on_frame_done ( +struct xen_drm_front_drm_pipeline *pipeline, +uint64_t fb_cookie) +{ +drm_crtc_handle_vblank (&pipeline->pipe.crtc);
Hm, again this doesn't look like real vblank, but only a page-flip done event. If that's correct then please don't use the vblank machinery, but just store the event internally (protected with your own private spinlock) and send it out using drm_crtc_send_vblank_event directly. No calls to arm_vblank_event or any of the other vblank infrastructure should be needed.
Also please remove the drm_vblank_init() call, since your hw doesn't really have vblanks. And exposing vblanks to userspace without implementing them is confusing.
Quoted 45 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +45
-0+} + +static void display_send_page_flip (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *old_plane_state) +{ +struct drm_plane_state *plane_state =drm_atomic_get_new_plane_state ( + old_plane_state->state, &pipe->plane); + +/* +* If old_plane_state->fb is NULL and plane_state->fb is not, +* then this is an atomic commit which will enable display. +* If old_plane_state->fb is not NULL and plane_state->fb is, +* then this is an atomic commit which will disable display. +* Ignore these and do not send page flip as this framebuffer will be +* sent to the backend as a part of display_set_config call. +*/ +if (old_plane_state->fb && plane_state->fb) { +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe); +struct xen_drm_front_drm_info *drm_info = pipeline->drm_info; +int ret; + + ret = drm_info->front_ops->page_flip (drm_info->front_info, + pipeline->index, +xen_drm_front_fb_to_cookie (plane_state->fb)); + pipeline->pgflip_last_error = ret; +if (ret) { +DRM_ERROR ("Failed to send page flip request to backend: %d\n" , ret); +/* +* As we are at commit stage the DRM core will anyways +* wait for the vblank and knows nothing about our +* failure. The best we can do is to handle +* vblank now, so there is no vblank/flip_done +* time outs +*/ +drm_crtc_handle_vblank (&pipeline->pipe.crtc); + } + } +} + +static int display_prepare_fb (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *plane_state) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe);
drivers/gpu/drm/xen/xen_drm_front_kms.c line 207
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +10
-0+ +if (pipeline->pgflip_last_error) { +int ret; + +/* if previous page flip didn't succeed then report the error */ + ret = pipeline->pgflip_last_error; +/* and let us try to page flip next time */ + pipeline->pgflip_last_error =0 ; +return ret; + }
Nope, this isn't how the uapi works. If your flips fail then we might need to add some error status thing to the drm events, but you can't make the next flip fail.
-Daniel
Quoted 135 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +92
-0+return drm_gem_fb_prepare_fb (&pipe->plane, plane_state); +} + +static void display_update (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *old_plane_state) +{ +struct drm_crtc *crtc = &pipe->crtc; +struct drm_pending_vblank_event *event; + + event = crtc->state->event; +if (event) { +struct drm_device *dev = crtc->dev; +unsigned long flags; + + crtc->state->event =NULL ; + +spin_lock_irqsave (&dev->event_lock, flags); +if (drm_crtc_vblank_get (crtc) ==0 ) +drm_crtc_arm_vblank_event (crtc, event); +else +drm_crtc_send_vblank_event (crtc, event); +spin_unlock_irqrestore (&dev->event_lock, flags); + } +/* +* Send page flip request to the backend *after* we have event armed/ +* sent above, so on page flip done event from the backend we can +* deliver it while handling vblank. +*/ +display_send_page_flip (pipe, old_plane_state); +} + +static const struct drm_simple_display_pipe_funcs display_funcs = { + .enable = display_enable, + .disable = display_disable, + .prepare_fb = display_prepare_fb, + .update = display_update, +}; + +static int display_pipe_init (struct xen_drm_front_drm_info *drm_info, +int index,struct xen_drm_front_cfg_connector *cfg, +struct xen_drm_front_drm_pipeline *pipeline) +{ +struct drm_device *dev = drm_info->drm_dev; +const uint32_t *formats; +int format_count; +int ret; + + pipeline->drm_info = drm_info; + pipeline->index = index; + pipeline->height = cfg->height; + pipeline->width = cfg->width; + + ret =xen_drm_front_conn_init (drm_info, &pipeline->conn); +if (ret) +return ret; + + formats =xen_drm_front_conn_get_formats (&format_count); + +return drm_simple_display_pipe_init (dev, &pipeline->pipe, + &display_funcs, formats, format_count, +NULL , &pipeline->conn); +} + +int xen_drm_front_kms_init (struct xen_drm_front_drm_info *drm_info) +{ +struct drm_device *dev = drm_info->drm_dev; +int i, ret; + +drm_mode_config_init (dev); + + dev->mode_config.min_width =0 ; + dev->mode_config.min_height =0 ; + dev->mode_config.max_width =4095 ; + dev->mode_config.max_height =2047 ; + dev->mode_config.funcs = &mode_config_funcs; + +for (i =0 ; i < drm_info->cfg->num_connectors; i++) { +struct xen_drm_front_cfg_connector *cfg = + &drm_info->cfg->connectors[i]; +struct xen_drm_front_drm_pipeline *pipeline = + &drm_info->pipeline[i]; + + ret =display_pipe_init (drm_info, i, cfg, pipeline); +if (ret) { +drm_mode_config_cleanup (dev); +return ret; + } + } + +drm_mode_config_reset (dev); +return 0 ; +}drivers/gpu/drm/xen/xen_drm_front_kms.h new file +30
-0@@ -0,0 +1,30 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_KMS_H_ +#define __XEN_DRM_FRONT_KMS_H_ + +#include "xen_drm_front_drv.h" + +int xen_drm_front_kms_init (struct xen_drm_front_drm_info *drm_info); + +void xen_drm_front_kms_on_frame_done ( +struct xen_drm_front_drm_pipeline *pipeline, +uint64_t fb_cookie); + +#endif /* __XEN_DRM_FRONT_KMS_H_ */ Signature · 6 lines
2.7.4 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Signature · 7 lines
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 7/9] drm/xen-front: Implement KMS/connector handling
Quoted 26 lines · Daniel Vetter
Quoted 25 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Implement kernel modesetiing/connector handling using DRM simple KMS helper pipeline:
- implement KMS part of the driver with the help of DRM simple pipepline helper which is possible due to the fact that the para-virtualized driver only supports a single (primary) plane:
- initialize connectors according to XenStore configuration
- handle frame done events from the backend
- generate vblank events
- create and destroy frame buffers and propagate those to the backend
- propagate set/reset mode configuration to the backend on display enable/disable callbacks
- send page flip request to the backend and implement logic for reporting backend IO errors on prepare fb callback- implement virtual connector handling:
- support only pixel formats suitable for single plane modes
- make sure the connector is always connected
- support a single video mode as per para-virtualized driver configuration
Quoted 3 lines
Quoted 1 line
Signed-off-by Oleksandr Andrushchenko <[email protected]>I think once you've removed the midlayer in the previous patch it would makes sense to merge the 2 patches into 1.
ok, will squash the two
Quoted 400 lines
Bunch more comments below.
-DanielQuoted 396 lines
--- drivers/gpu/drm/xen/Makefile | 2 + drivers/gpu/drm/xen/xen_drm_front_conn.c | 125 +++++++++++++ drivers/gpu/drm/xen/xen_drm_front_conn.h | 35 ++++ drivers/gpu/drm/xen/xen_drm_front_drv.c | 15 ++ drivers/gpu/drm/xen/xen_drm_front_drv.h | 12 ++ drivers/gpu/drm/xen/xen_drm_front_kms.c | 299 +++++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_kms.h | 30 ++++ 7 files changed, 518 insertions(+)create mode 100644
drivers/gpu/drm/xen/xen_drm_front_conn.ccreate mode 100644drivers/gpu/drm/xen/xen_drm_front_conn.hcreate mode 100644drivers/gpu/drm/xen/xen_drm_front_kms.ccreate mode 100644drivers/gpu/drm/xen/xen_drm_front_kms.hdrivers/gpu/drm/xen/Makefile +2
-0@@ -2,6 +2,8 @@ drm_xen_front-objs := xen_drm_front.o \ xen_drm_front_drv.o \ + xen_drm_front_kms.o \ + xen_drm_front_conn.o \ xen_drm_front_evtchnl.o \ xen_drm_front_shbuf.o \ xen_drm_front_cfg.odrivers/gpu/drm/xen/xen_drm_front_conn.c new file +125
-0@@ -0,0 +1,125 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_crtc_helper.h> + +#include <video/videomode.h> + +#include "xen_drm_front_conn.h" +#include "xen_drm_front_drv.h" + +static struct xen_drm_front_drm_pipeline * +to_xen_drm_pipeline (struct drm_connector *connector) +{ + return container_of(connector, struct xen_drm_front_drm_pipeline, conn); +} + +static const uint32_t plane_formats[] = { +DRM_FORMAT_RGB565 , +DRM_FORMAT_RGB888 , +DRM_FORMAT_XRGB8888 , +DRM_FORMAT_ARGB8888 , +DRM_FORMAT_XRGB4444 , +DRM_FORMAT_ARGB4444 , +DRM_FORMAT_XRGB1555 , +DRM_FORMAT_ARGB1555 , +}; + +const uint32_t *xen_drm_front_conn_get_formats (int *format_count) +{ + *format_count =ARRAY_SIZE (plane_formats); +return plane_formats; +} + +static enum drm_connector_status connector_detect ( +struct drm_connector *connector,bool force) +{ +if (drm_dev_is_unplugged (connector->dev)) +return connector_status_disconnected; + +return connector_status_connected; +} + +#define XEN_DRM_NUM_VIDEO_MODES 1 +#define XEN_DRM_CRTC_VREFRESH_HZ 60 + +static int connector_get_modes (struct drm_connector *connector) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (connector); +struct drm_display_mode *mode; +struct videomode videomode; +int width, height; + + mode =drm_mode_create (connector->dev); +if (!mode) +return 0 ; + +memset (&videomode,0 ,sizeof (videomode)); + videomode.hactive = pipeline->width; + videomode.vactive = pipeline->height; + width = videomode.hactive + videomode.hfront_porch + + videomode.hback_porch + videomode.hsync_len; + height = videomode.vactive + videomode.vfront_porch + + videomode.vback_porch + videomode.vsync_len; + videomode.pixelclock = width * height *XEN_DRM_CRTC_VREFRESH_HZ ; + mode->type =DRM_MODE_TYPE_PREFERRED |DRM_MODE_TYPE_DRIVER ; + +drm_display_mode_from_videomode (&videomode, mode); +drm_mode_probed_add (connector, mode); +return XEN_DRM_NUM_VIDEO_MODES ; +} + +static int connector_mode_valid (struct drm_connector *connector, +struct drm_display_mode *mode) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (connector); + +if (mode->hdisplay != pipeline->width) +return MODE_ERROR ; + +if (mode->vdisplay != pipeline->height) +return MODE_ERROR ; + +return MODE_OK ; +} + +static const struct drm_connector_helper_funcs connector_helper_funcs = { + .get_modes = connector_get_modes, + .mode_valid = connector_mode_valid, +}; + +static const struct drm_connector_funcs connector_funcs = { + .detect = connector_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +int xen_drm_front_conn_init (struct xen_drm_front_drm_info *drm_info, +struct drm_connector *connector) +{ +drm_connector_helper_add (connector, &connector_helper_funcs); + +return drm_connector_init (drm_info->drm_dev, connector, + &connector_funcs,DRM_MODE_CONNECTOR_VIRTUAL ); +}drivers/gpu/drm/xen/xen_drm_front_conn.h new file +35
-0@@ -0,0 +1,35 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_CONN_H_ +#define __XEN_DRM_FRONT_CONN_H_ + +#include <drm/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_encoder.h> + +#include <linux/wait.h> + +struct xen_drm_front_drm_info ; + +const uint32_t *xen_drm_front_conn_get_formats (int *format_count); + +int xen_drm_front_conn_init (struct xen_drm_front_drm_info *drm_info, +struct drm_connector *connector); + +#endif /* __XEN_DRM_FRONT_CONN_H_ */ drivers/gpu/drm/xen/xen_drm_front_drv.c +15
-0@@ -23,6 +23,7 @@#include "xen_drm_front.h" #include "xen_drm_front_cfg.h" #include "xen_drm_front_drv.h" +#include "xen_drm_front_kms.h" static int dumb_create (struct drm_file *filp,struct drm_device *dev,struct drm_mode_create_dumb *args)@@ -41,6 +42,13 @@ static void free_object(struct drm_gem_object *obj)static void on_frame_done (struct platform_device *pdev,int conn_idx,uint64_t fb_cookie) { +struct xen_drm_front_drm_info *drm_info =platform_get_drvdata (pdev); + +if (unlikely (conn_idx >= drm_info->cfg->num_connectors)) +return ; + +xen_drm_front_kms_on_frame_done (&drm_info->pipeline[conn_idx], + fb_cookie); }static void lastclose (struct drm_device *dev)@@ -157,6 +165,12 @@ int xen_drm_front_drv_probe(struct platform_device *pdev,return ret; } + ret =xen_drm_front_kms_init (drm_info); +if (ret) { +DRM_ERROR ("Failed to initialize DRM/KMS, ret %d\n" , ret); + goto fail_modeset; + } + dev->irq_enabled =1 ; ret =drm_dev_register (dev,0 );@@ -172,6 +186,7 @@ int xen_drm_front_drv_probe(struct platform_device *pdev, fail_register:drm_dev_unregister (dev); +fail_modeset:drm_mode_config_cleanup (dev);return ret; }drivers/gpu/drm/xen/xen_drm_front_drv.h +12
-0@@ -20,14 +20,24 @@#define __XEN_DRM_FRONT_DRV_H_#include <drm/drmP.h> +#include <drm/drm_simple_kms_helper.h> #include "xen_drm_front.h" #include "xen_drm_front_cfg.h" +#include "xen_drm_front_conn.h" struct xen_drm_front_drm_pipeline {struct xen_drm_front_drm_info *drm_info;int index; + +struct drm_simple_display_pipe pipe; + +struct drm_connector conn; +/* these are only for connector mode checking */ +int width, height; +/* last backend error seen on page flip */ +int pgflip_last_error; };struct xen_drm_front_drm_info {@@ -35,6 +45,8 @@ struct xen_drm_front_drm_info {struct xen_drm_front_ops *front_ops;struct drm_device *drm_dev;struct xen_drm_front_cfg *cfg; + +struct xen_drm_front_drm_pipeline pipeline[XEN_DRM_FRONT_MAX_CRTCS ]; }; static inline uint64_t xen_drm_front_fb_to_cookie(drivers/gpu/drm/xen/xen_drm_front_kms.c new file +106
-0@@ -0,0 +1,299 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include "xen_drm_front_kms.h" + +#include <drm/drmP.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_gem.h> +#include <drm/drm_gem_framebuffer_helper.h> + +#include "xen_drm_front.h" +#include "xen_drm_front_conn.h" +#include "xen_drm_front_drv.h" + +static struct xen_drm_front_drm_pipeline * +to_xen_drm_pipeline (struct drm_simple_display_pipe *pipe) +{ + return container_of(pipe, struct xen_drm_front_drm_pipeline, pipe); +} + +static void fb_destroy (struct drm_framebuffer *fb) +{ +struct xen_drm_front_drm_info *drm_info = fb->dev->dev_private; + + drm_info->front_ops->fb_detach (drm_info->front_info, +xen_drm_front_fb_to_cookie (fb)); +drm_gem_fb_destroy (fb); +} + +static struct drm_framebuffer_funcs fb_funcs = { + .destroy = fb_destroy, +}; + +static struct drm_framebuffer *fb_create (struct drm_device *dev, +struct drm_file *filp,const struct drm_mode_fb_cmd2 *mode_cmd) +{ +struct xen_drm_front_drm_info *drm_info = dev->dev_private; +static struct drm_framebuffer *fb; +struct drm_gem_object *gem_obj; +int ret; + + fb =drm_gem_fb_create_with_funcs (dev, filp, mode_cmd, &fb_funcs); +if (IS_ERR_OR_NULL (fb)) +return fb; + + gem_obj =drm_gem_object_lookup (filp, mode_cmd->handles[0 ]); +if (!gem_obj) { +DRM_ERROR ("Failed to lookup GEM object\n" ); + ret = -ENOENT ; + goto fail; + } + +drm_gem_object_unreference_unlocked (gem_obj); + + ret = drm_info->front_ops->fb_attach ( + drm_info->front_info, +xen_drm_front_dbuf_to_cookie (gem_obj), +xen_drm_front_fb_to_cookie (fb), + fb->width, fb->height, fb->format->format); +if (ret <0 ) { +DRM_ERROR ("Back failed to attach FB %p: %d\n" , fb, ret); + goto fail; + } + +return fb; + +fail: +drm_gem_fb_destroy (fb); +return ERR_PTR (ret); +} + +static const struct drm_mode_config_funcs mode_config_funcs = { + .fb_create = fb_create, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +static int display_set_config (struct drm_simple_display_pipe *pipe, +struct drm_framebuffer *fb) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe); +struct drm_crtc *crtc = &pipe->crtc; +struct xen_drm_front_drm_info *drm_info = pipeline->drm_info; +int ret; + +if (fb) + ret = drm_info->front_ops->mode_set(pipeline, + crtc->x, crtc->y, + fb->width, fb->height, fb->format->cpp[0] * 8,
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c line 111
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +5
-0+ xen_drm_front_fb_to_cookie(fb)); + else + ret = drm_info->front_ops->mode_set (pipeline, +0 ,0 ,0 ,0 ,0 , +xen_drm_front_fb_to_cookie (NULL ));This is a bit much layering, the if (fb) case corresponds to the display_enable/disable hooks, pls fold that in instead of the indirection. simple helpers guarantee that when the display is on, then you have an fb.
1. Ok, the only reason for having this function was to keep front_ops->mode_set calls at one place (will be refactored to be a direct call, not via front_ops).
2. The if (fb) check was meant not to check if simple helpers may give us some wrong value when we do not expect: there is nothing wrong with them. The check was for 2 cases when this function was called: with fb != NULL on display enable and with fb == NULL on display disable, e.g. fb was used as a flag in this check.
3. I will remove this function at all and will make direct calls to the backend on .display_{enable|disable}
Quoted 3 lines
Maybe we need to fix the docs, pls check and if that's not clear, submit a kernel-doc patch for the simple pipe helpers.
no, nothing wrong here, just see my reasoning above
Quoted 9 lines
Quoted 9 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +9
-0+ +if (ret) +DRM_ERROR ("Failed to set mode to back: %d\n" , ret); + +return ret; +} + +static void display_enable (struct drm_simple_display_pipe *pipe, +struct drm_crtc_state *crtc_state)
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c line 126
Quoted 6 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +6
-0+{ +struct drm_crtc *crtc = &pipe->crtc; +struct drm_framebuffer *fb = pipe->plane.state->fb; + +if (display_set_config (pipe, fb) ==0 ) +drm_crtc_vblank_on (crtc);I get the impression your driver doesn't support vblanks (the page flip code at least looks like it's only generating a single event),
yes, this is true
Quoted 2 lines
you also
don't have a enable/disable_vblank implementation.
this is because with my previous patches [1] these are now handled by simple helpers, so no need to provide dummy ones in the driver
Quoted 2 lines
If there's no vblank
handling then this shouldn't be needed.
yes, I will rework the code, please see below
Quoted 21 lines
Quoted 21 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +21
-0+else +DRM_ERROR ("Failed to enable display\n" ); +} + +static void display_disable (struct drm_simple_display_pipe *pipe) +{ +struct drm_crtc *crtc = &pipe->crtc; + +display_set_config (pipe,NULL ); +drm_crtc_vblank_off (crtc); +/* final check for stalled events */ +if (crtc->state->event && !crtc->state->active) { +unsigned long flags; + +spin_lock_irqsave (&crtc->dev->event_lock, flags); +drm_crtc_send_vblank_event (crtc, crtc->state->event); +spin_unlock_irqrestore (&crtc->dev->event_lock, flags); + crtc->state->event =NULL ; + } +} +
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c line 152
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +5
-0+void xen_drm_front_kms_on_frame_done ( +struct xen_drm_front_drm_pipeline *pipeline, +uint64_t fb_cookie) +{ +drm_crtc_handle_vblank (&pipeline->pipe.crtc);Hm, again this doesn't look like real vblank, but only a page-flip done event. If that's correct then please don't use the vblank machinery, but just store the event internally (protected with your own private spinlock)
Why can't I use &dev->event_lock? Anyways for handling page-flip events I will need to lock on it, so I can do drm_crtc_send_vblank_event?
Quoted 3 lines
and send it out using
drm_crtc_send_vblank_eventdirectly. No calls toarm_vblank_eventor any of the other vblank infrastructure should be needed.
will re-work, e.g. will store drm_pending_vblank_event on .display_update and send out on page flip event from the backend
Quoted 3 lines
Also please remove the
drm_vblank_init()call, since your hw doesn't really have vblanks. And exposing vblanks to userspace without implementing them is confusing.
will remove all vblank handling at all with the re-work above
Quoted 51 lines
Quoted 51 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +50
-0+} + +static void display_send_page_flip (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *old_plane_state) +{ +struct drm_plane_state *plane_state =drm_atomic_get_new_plane_state ( + old_plane_state->state, &pipe->plane); + +/* +* If old_plane_state->fb is NULL and plane_state->fb is not, +* then this is an atomic commit which will enable display. +* If old_plane_state->fb is not NULL and plane_state->fb is, +* then this is an atomic commit which will disable display. +* Ignore these and do not send page flip as this framebuffer will be +* sent to the backend as a part of display_set_config call. +*/ +if (old_plane_state->fb && plane_state->fb) { +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe); +struct xen_drm_front_drm_info *drm_info = pipeline->drm_info; +int ret; + + ret = drm_info->front_ops->page_flip (drm_info->front_info, + pipeline->index, +xen_drm_front_fb_to_cookie (plane_state->fb)); + pipeline->pgflip_last_error = ret; +if (ret) { +DRM_ERROR ("Failed to send page flip request to backend: %d\n" , ret); +/* +* As we are at commit stage the DRM core will anyways +* wait for the vblank and knows nothing about our +* failure. The best we can do is to handle +* vblank now, so there is no vblank/flip_done +* time outs +*/ +drm_crtc_handle_vblank (&pipeline->pipe.crtc); + } + } +} + +static int display_prepare_fb (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *plane_state) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe); + +if (pipeline->pgflip_last_error) { +int ret; + +/* if previous page flip didn't succeed then report the error */
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c line 207
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +5
-0+ ret = pipeline->pgflip_last_error; +/* and let us try to page flip next time */ + pipeline->pgflip_last_error =0 ; +return ret; + }Nope, this isn't how the uapi works. If your flips fail then we might need to add some error status thing to the drm events, but you can't make the next flip fail.
Well, yes, there is no way for me to tell that the page flip has failed, so this is why I tried to do this workaround with the next page-flip. The reason for that is that if, for example, we are disconnected from the backend for some reason, there is no way for me to tell the user-space that hey, please, do not send any other page flips. If backend can recover and that was a one time error then yes, the code I have will do wrong thing (fail the current page flip), but if the error state is persistent then I will be able to tell the user-space to stop by returning errors. This is kind of trade-off which I am not sure how to solve correctly.
Do you think I can remove this workaround completely?
Quoted 133 lines
-Daniel
Quoted 131 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +92
-0+return drm_gem_fb_prepare_fb (&pipe->plane, plane_state); +} + +static void display_update (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *old_plane_state) +{ +struct drm_crtc *crtc = &pipe->crtc; +struct drm_pending_vblank_event *event; + + event = crtc->state->event; +if (event) { +struct drm_device *dev = crtc->dev; +unsigned long flags; + + crtc->state->event =NULL ; + +spin_lock_irqsave (&dev->event_lock, flags); +if (drm_crtc_vblank_get (crtc) ==0 ) +drm_crtc_arm_vblank_event (crtc, event); +else +drm_crtc_send_vblank_event (crtc, event); +spin_unlock_irqrestore (&dev->event_lock, flags); + } +/* +* Send page flip request to the backend *after* we have event armed/ +* sent above, so on page flip done event from the backend we can +* deliver it while handling vblank. +*/ +display_send_page_flip (pipe, old_plane_state); +} + +static const struct drm_simple_display_pipe_funcs display_funcs = { + .enable = display_enable, + .disable = display_disable, + .prepare_fb = display_prepare_fb, + .update = display_update, +}; + +static int display_pipe_init (struct xen_drm_front_drm_info *drm_info, +int index,struct xen_drm_front_cfg_connector *cfg, +struct xen_drm_front_drm_pipeline *pipeline) +{ +struct drm_device *dev = drm_info->drm_dev; +const uint32_t *formats; +int format_count; +int ret; + + pipeline->drm_info = drm_info; + pipeline->index = index; + pipeline->height = cfg->height; + pipeline->width = cfg->width; + + ret =xen_drm_front_conn_init (drm_info, &pipeline->conn); +if (ret) +return ret; + + formats =xen_drm_front_conn_get_formats (&format_count); + +return drm_simple_display_pipe_init (dev, &pipeline->pipe, + &display_funcs, formats, format_count, +NULL , &pipeline->conn); +} + +int xen_drm_front_kms_init (struct xen_drm_front_drm_info *drm_info) +{ +struct drm_device *dev = drm_info->drm_dev; +int i, ret; + +drm_mode_config_init (dev); + + dev->mode_config.min_width =0 ; + dev->mode_config.min_height =0 ; + dev->mode_config.max_width =4095 ; + dev->mode_config.max_height =2047 ; + dev->mode_config.funcs = &mode_config_funcs; + +for (i =0 ; i < drm_info->cfg->num_connectors; i++) { +struct xen_drm_front_cfg_connector *cfg = + &drm_info->cfg->connectors[i]; +struct xen_drm_front_drm_pipeline *pipeline = + &drm_info->pipeline[i]; + + ret =display_pipe_init (drm_info, i, cfg, pipeline); +if (ret) { +drm_mode_config_cleanup (dev); +return ret; + } + } + +drm_mode_config_reset (dev); +return 0 ; +}drivers/gpu/drm/xen/xen_drm_front_kms.h new file +30
-0@@ -0,0 +1,30 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_KMS_H_ +#define __XEN_DRM_FRONT_KMS_H_ + +#include "xen_drm_front_drv.h" + +int xen_drm_front_kms_init (struct xen_drm_front_drm_info *drm_info); + +void xen_drm_front_kms_on_frame_done ( +struct xen_drm_front_drm_pipeline *pipeline, +uint64_t fb_cookie); + +#endif /* __XEN_DRM_FRONT_KMS_H_ */ Signature · 1 line
2.7.4
Quoted 4 lines
Quoted 4 lines
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
[1] https://patchwork.kernel.org/patch/10211997/
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 7/9] drm/xen-front: Implement KMS/connector handling
Quoted 427 lines · Oleksandr Andrushchenko
Quoted 26 lines · Daniel Vetter
Quoted 25 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Implement kernel modesetiing/connector handling using DRM simple KMS helper pipeline:
- implement KMS part of the driver with the help of DRM simple pipepline helper which is possible due to the fact that the para-virtualized driver only supports a single (primary) plane:
- initialize connectors according to XenStore configuration
- handle frame done events from the backend
- generate vblank events
- create and destroy frame buffers and propagate those to the backend
- propagate set/reset mode configuration to the backend on display enable/disable callbacks
- send page flip request to the backend and implement logic for reporting backend IO errors on prepare fb callback- implement virtual connector handling:
- support only pixel formats suitable for single plane modes
- make sure the connector is always connected
- support a single video mode as per para-virtualized driver configurationQuoted 3 lines
Quoted 1 line
Signed-off-by Oleksandr Andrushchenko <[email protected]>I think once you've removed the midlayer in the previous patch it would makes sense to merge the 2 patches into 1.
ok, will squash the two
Quoted 388 lines
Bunch more comments below.
-DanielQuoted 384 lines
--- drivers/gpu/drm/xen/Makefile | 2 + drivers/gpu/drm/xen/xen_drm_front_conn.c | 125 +++++++++++++ drivers/gpu/drm/xen/xen_drm_front_conn.h | 35 ++++ drivers/gpu/drm/xen/xen_drm_front_drv.c | 15 ++ drivers/gpu/drm/xen/xen_drm_front_drv.h | 12 ++ drivers/gpu/drm/xen/xen_drm_front_kms.c | 299 +++++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_kms.h | 30 ++++ 7 files changed, 518 insertions(+)create mode 100644
drivers/gpu/drm/xen/xen_drm_front_conn.ccreate mode 100644drivers/gpu/drm/xen/xen_drm_front_conn.hcreate mode 100644drivers/gpu/drm/xen/xen_drm_front_kms.ccreate mode 100644drivers/gpu/drm/xen/xen_drm_front_kms.hdrivers/gpu/drm/xen/Makefile +2
-0@@ -2,6 +2,8 @@ drm_xen_front-objs := xen_drm_front.o \ xen_drm_front_drv.o \ + xen_drm_front_kms.o \ + xen_drm_front_conn.o \ xen_drm_front_evtchnl.o \ xen_drm_front_shbuf.o \ xen_drm_front_cfg.odrivers/gpu/drm/xen/xen_drm_front_conn.c new file +125
-0@@ -0,0 +1,125 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_crtc_helper.h> + +#include <video/videomode.h> + +#include "xen_drm_front_conn.h" +#include "xen_drm_front_drv.h" + +static struct xen_drm_front_drm_pipeline * +to_xen_drm_pipeline (struct drm_connector *connector) +{ + return container_of(connector, struct xen_drm_front_drm_pipeline, conn); +} + +static const uint32_t plane_formats[] = { +DRM_FORMAT_RGB565 , +DRM_FORMAT_RGB888 , +DRM_FORMAT_XRGB8888 , +DRM_FORMAT_ARGB8888 , +DRM_FORMAT_XRGB4444 , +DRM_FORMAT_ARGB4444 , +DRM_FORMAT_XRGB1555 , +DRM_FORMAT_ARGB1555 , +}; + +const uint32_t *xen_drm_front_conn_get_formats (int *format_count) +{ + *format_count =ARRAY_SIZE (plane_formats); +return plane_formats; +} + +static enum drm_connector_status connector_detect ( +struct drm_connector *connector,bool force) +{ +if (drm_dev_is_unplugged (connector->dev)) +return connector_status_disconnected; + +return connector_status_connected; +} + +#define XEN_DRM_NUM_VIDEO_MODES 1 +#define XEN_DRM_CRTC_VREFRESH_HZ 60 + +static int connector_get_modes (struct drm_connector *connector) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (connector); +struct drm_display_mode *mode; +struct videomode videomode; +int width, height; + + mode =drm_mode_create (connector->dev); +if (!mode) +return 0 ; + +memset (&videomode,0 ,sizeof (videomode)); + videomode.hactive = pipeline->width; + videomode.vactive = pipeline->height; + width = videomode.hactive + videomode.hfront_porch + + videomode.hback_porch + videomode.hsync_len; + height = videomode.vactive + videomode.vfront_porch + + videomode.vback_porch + videomode.vsync_len; + videomode.pixelclock = width * height *XEN_DRM_CRTC_VREFRESH_HZ ; + mode->type =DRM_MODE_TYPE_PREFERRED |DRM_MODE_TYPE_DRIVER ; + +drm_display_mode_from_videomode (&videomode, mode); +drm_mode_probed_add (connector, mode); +return XEN_DRM_NUM_VIDEO_MODES ; +} + +static int connector_mode_valid (struct drm_connector *connector, +struct drm_display_mode *mode) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (connector); + +if (mode->hdisplay != pipeline->width) +return MODE_ERROR ; + +if (mode->vdisplay != pipeline->height) +return MODE_ERROR ; + +return MODE_OK ; +} + +static const struct drm_connector_helper_funcs connector_helper_funcs = { + .get_modes = connector_get_modes, + .mode_valid = connector_mode_valid, +}; + +static const struct drm_connector_funcs connector_funcs = { + .detect = connector_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +int xen_drm_front_conn_init (struct xen_drm_front_drm_info *drm_info, +struct drm_connector *connector) +{ +drm_connector_helper_add (connector, &connector_helper_funcs); + +return drm_connector_init (drm_info->drm_dev, connector, + &connector_funcs,DRM_MODE_CONNECTOR_VIRTUAL ); +}drivers/gpu/drm/xen/xen_drm_front_conn.h new file +35
-0@@ -0,0 +1,35 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_CONN_H_ +#define __XEN_DRM_FRONT_CONN_H_ + +#include <drm/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_encoder.h> + +#include <linux/wait.h> + +struct xen_drm_front_drm_info ; + +const uint32_t *xen_drm_front_conn_get_formats (int *format_count); + +int xen_drm_front_conn_init (struct xen_drm_front_drm_info *drm_info, +struct drm_connector *connector); + +#endif /* __XEN_DRM_FRONT_CONN_H_ */ drivers/gpu/drm/xen/xen_drm_front_drv.c +15
-0@@ -23,6 +23,7 @@#include "xen_drm_front.h" #include "xen_drm_front_cfg.h" #include "xen_drm_front_drv.h" +#include "xen_drm_front_kms.h" static int dumb_create (struct drm_file *filp,struct drm_device *dev,struct drm_mode_create_dumb *args)@@ -41,6 +42,13 @@ static void free_object(struct drm_gem_object *obj)static void on_frame_done (struct platform_device *pdev,int conn_idx,uint64_t fb_cookie) { +struct xen_drm_front_drm_info *drm_info =platform_get_drvdata (pdev); + +if (unlikely (conn_idx >= drm_info->cfg->num_connectors)) +return ; + +xen_drm_front_kms_on_frame_done (&drm_info->pipeline[conn_idx], + fb_cookie); }static void lastclose (struct drm_device *dev)@@ -157,6 +165,12 @@ int xen_drm_front_drv_probe(struct platform_device *pdev,return ret; } + ret =xen_drm_front_kms_init (drm_info); +if (ret) { +DRM_ERROR ("Failed to initialize DRM/KMS, ret %d\n" , ret); + goto fail_modeset; + } + dev->irq_enabled =1 ; ret =drm_dev_register (dev,0 );@@ -172,6 +186,7 @@ int xen_drm_front_drv_probe(struct platform_device *pdev, fail_register:drm_dev_unregister (dev); +fail_modeset:drm_mode_config_cleanup (dev);return ret; }drivers/gpu/drm/xen/xen_drm_front_drv.h +12
-0@@ -20,14 +20,24 @@#define __XEN_DRM_FRONT_DRV_H_#include <drm/drmP.h> +#include <drm/drm_simple_kms_helper.h> #include "xen_drm_front.h" #include "xen_drm_front_cfg.h" +#include "xen_drm_front_conn.h" struct xen_drm_front_drm_pipeline {struct xen_drm_front_drm_info *drm_info;int index; + +struct drm_simple_display_pipe pipe; + +struct drm_connector conn; +/* these are only for connector mode checking */ +int width, height; +/* last backend error seen on page flip */ +int pgflip_last_error; };struct xen_drm_front_drm_info {@@ -35,6 +45,8 @@ struct xen_drm_front_drm_info {struct xen_drm_front_ops *front_ops;struct drm_device *drm_dev;struct xen_drm_front_cfg *cfg; + +struct xen_drm_front_drm_pipeline pipeline[XEN_DRM_FRONT_MAX_CRTCS ]; }; static inline uint64_t xen_drm_front_fb_to_cookie(drivers/gpu/drm/xen/xen_drm_front_kms.c new file +106
-0@@ -0,0 +1,299 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include "xen_drm_front_kms.h" + +#include <drm/drmP.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_gem.h> +#include <drm/drm_gem_framebuffer_helper.h> + +#include "xen_drm_front.h" +#include "xen_drm_front_conn.h" +#include "xen_drm_front_drv.h" + +static struct xen_drm_front_drm_pipeline * +to_xen_drm_pipeline (struct drm_simple_display_pipe *pipe) +{ + return container_of(pipe, struct xen_drm_front_drm_pipeline, pipe); +} + +static void fb_destroy (struct drm_framebuffer *fb) +{ +struct xen_drm_front_drm_info *drm_info = fb->dev->dev_private; + + drm_info->front_ops->fb_detach (drm_info->front_info, +xen_drm_front_fb_to_cookie (fb)); +drm_gem_fb_destroy (fb); +} + +static struct drm_framebuffer_funcs fb_funcs = { + .destroy = fb_destroy, +}; + +static struct drm_framebuffer *fb_create (struct drm_device *dev, +struct drm_file *filp,const struct drm_mode_fb_cmd2 *mode_cmd) +{ +struct xen_drm_front_drm_info *drm_info = dev->dev_private; +static struct drm_framebuffer *fb; +struct drm_gem_object *gem_obj; +int ret; + + fb =drm_gem_fb_create_with_funcs (dev, filp, mode_cmd, &fb_funcs); +if (IS_ERR_OR_NULL (fb)) +return fb; + + gem_obj =drm_gem_object_lookup (filp, mode_cmd->handles[0 ]); +if (!gem_obj) { +DRM_ERROR ("Failed to lookup GEM object\n" ); + ret = -ENOENT ; + goto fail; + } + +drm_gem_object_unreference_unlocked (gem_obj); + + ret = drm_info->front_ops->fb_attach ( + drm_info->front_info, +xen_drm_front_dbuf_to_cookie (gem_obj), +xen_drm_front_fb_to_cookie (fb), + fb->width, fb->height, fb->format->format); +if (ret <0 ) { +DRM_ERROR ("Back failed to attach FB %p: %d\n" , fb, ret); + goto fail; + } + +return fb; + +fail: +drm_gem_fb_destroy (fb); +return ERR_PTR (ret); +} + +static const struct drm_mode_config_funcs mode_config_funcs = { + .fb_create = fb_create, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +static int display_set_config (struct drm_simple_display_pipe *pipe, +struct drm_framebuffer *fb) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe); +struct drm_crtc *crtc = &pipe->crtc; +struct xen_drm_front_drm_info *drm_info = pipeline->drm_info; +int ret; + +if (fb) + ret = drm_info->front_ops->mode_set(pipeline, + crtc->x, crtc->y, + fb->width, fb->height, fb->format->cpp[0] * 8,Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c line 111
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +5
-0+ xen_drm_front_fb_to_cookie(fb)); + else + ret = drm_info->front_ops->mode_set (pipeline, +0 ,0 ,0 ,0 ,0 , +xen_drm_front_fb_to_cookie (NULL ));This is a bit much layering, the if (fb) case corresponds to the display_enable/disable hooks, pls fold that in instead of the indirection. simple helpers guarantee that when the display is on, then you have an fb.
Quoted 9 lines
1. Ok, the only reason for having this function was to keep
front_ops->mode_setcalls at one place (will be refactored to be a direct call, not viafront_ops).
2. The if (fb) check was meant not to check if simple helpers may give us some wrong value when we do not expect: there is nothing wrong with them. The check was for 2 cases when this function was called: with fb != NULL on display enable and with fb == NULL on display disable, e.g. fb was used as a flag in this check.
Yeah that's what I meant - it is needlessly confusing: You get 2 explicit enable/disable callbacks, then you squash them into 1 function call, only to require an
if (do_I_need_to_enable_or_disable) {
/* code that really should be directly put in the enable callback */
} else {
/* code that really should be directly put in the enable callback */
}Just a bit of indirection where I didnt' see the point.
Aside for why this matters: When refactoring the entire subsystem you need to be able to quickly understand how all the drivers work in a specific case, without being an expert on that driver. If there's very little indirection between the shared drm concepts/structs/callbacks and the actual driver code, then that's easy. If there's a bunch of callback layers or indirections like the above, you make subsystem refactoring harder for no reason. And in upstream we optimize for the overall subsystem, not individual drivers.
Quoted 60 lines
3. I will remove this function at all and will make direct calls to the backend on .display_{enable|disable}
Quoted 3 lines
Maybe we need to fix the docs, pls check and if that's not clear, submit a kernel-doc patch for the simple pipe helpers.
no, nothing wrong here, just see my reasoning above
Quoted 9 lines
Quoted 9 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +9
-0+ +if (ret) +DRM_ERROR ("Failed to set mode to back: %d\n" , ret); + +return ret; +} + +static void display_enable (struct drm_simple_display_pipe *pipe, +struct drm_crtc_state *crtc_state)Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c line 126
Quoted 6 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +6
-0+{ +struct drm_crtc *crtc = &pipe->crtc; +struct drm_framebuffer *fb = pipe->plane.state->fb; + +if (display_set_config (pipe, fb) ==0 ) +drm_crtc_vblank_on (crtc);I get the impression your driver doesn't support vblanks (the page flip code at least looks like it's only generating a single event),
yes, this is true
Quoted 2 lines
you also
don't have a enable/disable_vblank implementation.this is because with my previous patches [1] these are now handled by simple helpers, so no need to provide dummy ones in the driver
Quoted 2 lines
If there's no vblank
handling then this shouldn't be needed.yes, I will rework the code, please see below
Quoted 21 lines
Quoted 21 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +21
-0+else +DRM_ERROR ("Failed to enable display\n" ); +} + +static void display_disable (struct drm_simple_display_pipe *pipe) +{ +struct drm_crtc *crtc = &pipe->crtc; + +display_set_config (pipe,NULL ); +drm_crtc_vblank_off (crtc); +/* final check for stalled events */ +if (crtc->state->event && !crtc->state->active) { +unsigned long flags; + +spin_lock_irqsave (&crtc->dev->event_lock, flags); +drm_crtc_send_vblank_event (crtc, crtc->state->event); +spin_unlock_irqrestore (&crtc->dev->event_lock, flags); + crtc->state->event =NULL ; + } +} +Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c line 152
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +5
-0+void xen_drm_front_kms_on_frame_done ( +struct xen_drm_front_drm_pipeline *pipeline, +uint64_t fb_cookie) +{ +drm_crtc_handle_vblank (&pipeline->pipe.crtc);Hm, again this doesn't look like real vblank, but only a page-flip done event. If that's correct then please don't use the vblank machinery, but just store the event internally (protected with your own private spinlock)
Quoted 3 lines
Why can't I use
&dev->event_lock? Anyways for handling page-flip events I will need to lock on it, so I can dodrm_crtc_send_vblank_event?
Yeah you can reuse the event_lock too, that's what many drivers do.
Quoted 80 lines
Quoted 3 lines
and send it out using
drm_crtc_send_vblank_eventdirectly. No calls toarm_vblank_eventor any of the other vblank infrastructure should be needed.will re-work, e.g. will store
drm_pending_vblank_eventon .display_update and send out on page flip event from the backendQuoted 3 lines
Also please remove the
drm_vblank_init()call, since your hw doesn't really have vblanks. And exposing vblanks to userspace without implementing them is confusing.will remove all vblank handling at all with the re-work above
Quoted 51 lines
Quoted 51 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +50
-0+} + +static void display_send_page_flip (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *old_plane_state) +{ +struct drm_plane_state *plane_state =drm_atomic_get_new_plane_state ( + old_plane_state->state, &pipe->plane); + +/* +* If old_plane_state->fb is NULL and plane_state->fb is not, +* then this is an atomic commit which will enable display. +* If old_plane_state->fb is not NULL and plane_state->fb is, +* then this is an atomic commit which will disable display. +* Ignore these and do not send page flip as this framebuffer will be +* sent to the backend as a part of display_set_config call. +*/ +if (old_plane_state->fb && plane_state->fb) { +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe); +struct xen_drm_front_drm_info *drm_info = pipeline->drm_info; +int ret; + + ret = drm_info->front_ops->page_flip (drm_info->front_info, + pipeline->index, +xen_drm_front_fb_to_cookie (plane_state->fb)); + pipeline->pgflip_last_error = ret; +if (ret) { +DRM_ERROR ("Failed to send page flip request to backend: %d\n" , ret); +/* +* As we are at commit stage the DRM core will anyways +* wait for the vblank and knows nothing about our +* failure. The best we can do is to handle +* vblank now, so there is no vblank/flip_done +* time outs +*/ +drm_crtc_handle_vblank (&pipeline->pipe.crtc); + } + } +} + +static int display_prepare_fb (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *plane_state) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe); + +if (pipeline->pgflip_last_error) { +int ret; + +/* if previous page flip didn't succeed then report the error */ Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c line 207
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +5
-0+ ret = pipeline->pgflip_last_error; +/* and let us try to page flip next time */ + pipeline->pgflip_last_error =0 ; +return ret; + }Nope, this isn't how the uapi works. If your flips fail then we might need to add some error status thing to the drm events, but you can't make the next flip fail.
Well, yes, there is no way for me to tell that the page flip has failed, so this is why I tried to do this workaround with the next page-flip. The reason for that is that if, for example, we are disconnected from the backend for some reason, there is no way for me to tell the user-space that hey, please, do not send any other page flips. If backend can recover and that was a one time error then yes, the code I have will do wrong thing (fail the current page flip), but if the error state is persistent then I will be able to tell the user-space to stop by returning errors. This is kind of trade-off which I am not sure how to solve correctly.
Quoted 1 line
Do you think I can remove this workaround completely?
Yes. If you want to tell userspace that the backend is gone, send a hotplug uevent and update the connector status to disconnected. Hotplug uevents is how we tell userspace about asynchronous changes. We also have special stuff to signal display cable issue that might require picking a lower resolution (DP link training) and when HDCP encryption failed.
Sending back random errors on pageflips just confuses the compositor, and all correctly working compositors will listen to hotplug events and reprobe all the outputs and change the configuration if necessary. -Daniel
Quoted 142 lines
Quoted 133 lines
-Daniel
Quoted 131 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +92
-0+return drm_gem_fb_prepare_fb (&pipe->plane, plane_state); +} + +static void display_update (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *old_plane_state) +{ +struct drm_crtc *crtc = &pipe->crtc; +struct drm_pending_vblank_event *event; + + event = crtc->state->event; +if (event) { +struct drm_device *dev = crtc->dev; +unsigned long flags; + + crtc->state->event =NULL ; + +spin_lock_irqsave (&dev->event_lock, flags); +if (drm_crtc_vblank_get (crtc) ==0 ) +drm_crtc_arm_vblank_event (crtc, event); +else +drm_crtc_send_vblank_event (crtc, event); +spin_unlock_irqrestore (&dev->event_lock, flags); + } +/* +* Send page flip request to the backend *after* we have event armed/ +* sent above, so on page flip done event from the backend we can +* deliver it while handling vblank. +*/ +display_send_page_flip (pipe, old_plane_state); +} + +static const struct drm_simple_display_pipe_funcs display_funcs = { + .enable = display_enable, + .disable = display_disable, + .prepare_fb = display_prepare_fb, + .update = display_update, +}; + +static int display_pipe_init (struct xen_drm_front_drm_info *drm_info, +int index,struct xen_drm_front_cfg_connector *cfg, +struct xen_drm_front_drm_pipeline *pipeline) +{ +struct drm_device *dev = drm_info->drm_dev; +const uint32_t *formats; +int format_count; +int ret; + + pipeline->drm_info = drm_info; + pipeline->index = index; + pipeline->height = cfg->height; + pipeline->width = cfg->width; + + ret =xen_drm_front_conn_init (drm_info, &pipeline->conn); +if (ret) +return ret; + + formats =xen_drm_front_conn_get_formats (&format_count); + +return drm_simple_display_pipe_init (dev, &pipeline->pipe, + &display_funcs, formats, format_count, +NULL , &pipeline->conn); +} + +int xen_drm_front_kms_init (struct xen_drm_front_drm_info *drm_info) +{ +struct drm_device *dev = drm_info->drm_dev; +int i, ret; + +drm_mode_config_init (dev); + + dev->mode_config.min_width =0 ; + dev->mode_config.min_height =0 ; + dev->mode_config.max_width =4095 ; + dev->mode_config.max_height =2047 ; + dev->mode_config.funcs = &mode_config_funcs; + +for (i =0 ; i < drm_info->cfg->num_connectors; i++) { +struct xen_drm_front_cfg_connector *cfg = + &drm_info->cfg->connectors[i]; +struct xen_drm_front_drm_pipeline *pipeline = + &drm_info->pipeline[i]; + + ret =display_pipe_init (drm_info, i, cfg, pipeline); +if (ret) { +drm_mode_config_cleanup (dev); +return ret; + } + } + +drm_mode_config_reset (dev); +return 0 ; +}drivers/gpu/drm/xen/xen_drm_front_kms.h new file +30
-0@@ -0,0 +1,30 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_KMS_H_ +#define __XEN_DRM_FRONT_KMS_H_ + +#include "xen_drm_front_drv.h" + +int xen_drm_front_kms_init (struct xen_drm_front_drm_info *drm_info); + +void xen_drm_front_kms_on_frame_done ( +struct xen_drm_front_drm_pipeline *pipeline, +uint64_t fb_cookie); + +#endif /* __XEN_DRM_FRONT_KMS_H_ */ Signature · 1 line
2.7.4Quoted 4 lines
Quoted 4 lines
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel[1] https://patchwork.kernel.org/patch/10211997/
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Signature · 7 lines
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 7/9] drm/xen-front: Implement KMS/connector handling
Quoted 448 lines · Daniel Vetter
Quoted 426 lines · Oleksandr Andrushchenko
Quoted 26 lines · Daniel Vetter
Quoted 25 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Implement kernel modesetiing/connector handling using DRM simple KMS helper pipeline:
- implement KMS part of the driver with the help of DRM simple pipepline helper which is possible due to the fact that the para-virtualized driver only supports a single (primary) plane:
- initialize connectors according to XenStore configuration
- handle frame done events from the backend
- generate vblank events
- create and destroy frame buffers and propagate those to the backend
- propagate set/reset mode configuration to the backend on display enable/disable callbacks
- send page flip request to the backend and implement logic for reporting backend IO errors on prepare fb callback- implement virtual connector handling:
- support only pixel formats suitable for single plane modes
- make sure the connector is always connected
- support a single video mode as per para-virtualized driver configurationQuoted 3 lines
Quoted 1 line
Signed-off-by Oleksandr Andrushchenko <[email protected]>I think once you've removed the midlayer in the previous patch it would makes sense to merge the 2 patches into 1.
ok, will squash the two
Quoted 387 lines
Bunch more comments below.
-DanielQuoted 384 lines
--- drivers/gpu/drm/xen/Makefile | 2 + drivers/gpu/drm/xen/xen_drm_front_conn.c | 125 +++++++++++++ drivers/gpu/drm/xen/xen_drm_front_conn.h | 35 ++++ drivers/gpu/drm/xen/xen_drm_front_drv.c | 15 ++ drivers/gpu/drm/xen/xen_drm_front_drv.h | 12 ++ drivers/gpu/drm/xen/xen_drm_front_kms.c | 299 +++++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_kms.h | 30 ++++ 7 files changed, 518 insertions(+)create mode 100644
drivers/gpu/drm/xen/xen_drm_front_conn.ccreate mode 100644drivers/gpu/drm/xen/xen_drm_front_conn.hcreate mode 100644drivers/gpu/drm/xen/xen_drm_front_kms.ccreate mode 100644drivers/gpu/drm/xen/xen_drm_front_kms.hdrivers/gpu/drm/xen/Makefile +2
-0@@ -2,6 +2,8 @@ drm_xen_front-objs := xen_drm_front.o \ xen_drm_front_drv.o \ + xen_drm_front_kms.o \ + xen_drm_front_conn.o \ xen_drm_front_evtchnl.o \ xen_drm_front_shbuf.o \ xen_drm_front_cfg.odrivers/gpu/drm/xen/xen_drm_front_conn.c new file +125
-0@@ -0,0 +1,125 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_crtc_helper.h> + +#include <video/videomode.h> + +#include "xen_drm_front_conn.h" +#include "xen_drm_front_drv.h" + +static struct xen_drm_front_drm_pipeline * +to_xen_drm_pipeline (struct drm_connector *connector) +{ + return container_of(connector, struct xen_drm_front_drm_pipeline, conn); +} + +static const uint32_t plane_formats[] = { +DRM_FORMAT_RGB565 , +DRM_FORMAT_RGB888 , +DRM_FORMAT_XRGB8888 , +DRM_FORMAT_ARGB8888 , +DRM_FORMAT_XRGB4444 , +DRM_FORMAT_ARGB4444 , +DRM_FORMAT_XRGB1555 , +DRM_FORMAT_ARGB1555 , +}; + +const uint32_t *xen_drm_front_conn_get_formats (int *format_count) +{ + *format_count =ARRAY_SIZE (plane_formats); +return plane_formats; +} + +static enum drm_connector_status connector_detect ( +struct drm_connector *connector,bool force) +{ +if (drm_dev_is_unplugged (connector->dev)) +return connector_status_disconnected; + +return connector_status_connected; +} + +#define XEN_DRM_NUM_VIDEO_MODES 1 +#define XEN_DRM_CRTC_VREFRESH_HZ 60 + +static int connector_get_modes (struct drm_connector *connector) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (connector); +struct drm_display_mode *mode; +struct videomode videomode; +int width, height; + + mode =drm_mode_create (connector->dev); +if (!mode) +return 0 ; + +memset (&videomode,0 ,sizeof (videomode)); + videomode.hactive = pipeline->width; + videomode.vactive = pipeline->height; + width = videomode.hactive + videomode.hfront_porch + + videomode.hback_porch + videomode.hsync_len; + height = videomode.vactive + videomode.vfront_porch + + videomode.vback_porch + videomode.vsync_len; + videomode.pixelclock = width * height *XEN_DRM_CRTC_VREFRESH_HZ ; + mode->type =DRM_MODE_TYPE_PREFERRED |DRM_MODE_TYPE_DRIVER ; + +drm_display_mode_from_videomode (&videomode, mode); +drm_mode_probed_add (connector, mode); +return XEN_DRM_NUM_VIDEO_MODES ; +} + +static int connector_mode_valid (struct drm_connector *connector, +struct drm_display_mode *mode) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (connector); + +if (mode->hdisplay != pipeline->width) +return MODE_ERROR ; + +if (mode->vdisplay != pipeline->height) +return MODE_ERROR ; + +return MODE_OK ; +} + +static const struct drm_connector_helper_funcs connector_helper_funcs = { + .get_modes = connector_get_modes, + .mode_valid = connector_mode_valid, +}; + +static const struct drm_connector_funcs connector_funcs = { + .detect = connector_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +int xen_drm_front_conn_init (struct xen_drm_front_drm_info *drm_info, +struct drm_connector *connector) +{ +drm_connector_helper_add (connector, &connector_helper_funcs); + +return drm_connector_init (drm_info->drm_dev, connector, + &connector_funcs,DRM_MODE_CONNECTOR_VIRTUAL ); +}drivers/gpu/drm/xen/xen_drm_front_conn.h new file +35
-0@@ -0,0 +1,35 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_CONN_H_ +#define __XEN_DRM_FRONT_CONN_H_ + +#include <drm/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_encoder.h> + +#include <linux/wait.h> + +struct xen_drm_front_drm_info ; + +const uint32_t *xen_drm_front_conn_get_formats (int *format_count); + +int xen_drm_front_conn_init (struct xen_drm_front_drm_info *drm_info, +struct drm_connector *connector); + +#endif /* __XEN_DRM_FRONT_CONN_H_ */ drivers/gpu/drm/xen/xen_drm_front_drv.c +15
-0@@ -23,6 +23,7 @@#include "xen_drm_front.h" #include "xen_drm_front_cfg.h" #include "xen_drm_front_drv.h" +#include "xen_drm_front_kms.h" static int dumb_create (struct drm_file *filp,struct drm_device *dev,struct drm_mode_create_dumb *args)@@ -41,6 +42,13 @@ static void free_object(struct drm_gem_object *obj)static void on_frame_done (struct platform_device *pdev,int conn_idx,uint64_t fb_cookie) { +struct xen_drm_front_drm_info *drm_info =platform_get_drvdata (pdev); + +if (unlikely (conn_idx >= drm_info->cfg->num_connectors)) +return ; + +xen_drm_front_kms_on_frame_done (&drm_info->pipeline[conn_idx], + fb_cookie); }static void lastclose (struct drm_device *dev)@@ -157,6 +165,12 @@ int xen_drm_front_drv_probe(struct platform_device *pdev,return ret; } + ret =xen_drm_front_kms_init (drm_info); +if (ret) { +DRM_ERROR ("Failed to initialize DRM/KMS, ret %d\n" , ret); + goto fail_modeset; + } + dev->irq_enabled =1 ; ret =drm_dev_register (dev,0 );@@ -172,6 +186,7 @@ int xen_drm_front_drv_probe(struct platform_device *pdev, fail_register:drm_dev_unregister (dev); +fail_modeset:drm_mode_config_cleanup (dev);return ret; }drivers/gpu/drm/xen/xen_drm_front_drv.h +12
-0@@ -20,14 +20,24 @@#define __XEN_DRM_FRONT_DRV_H_#include <drm/drmP.h> +#include <drm/drm_simple_kms_helper.h> #include "xen_drm_front.h" #include "xen_drm_front_cfg.h" +#include "xen_drm_front_conn.h" struct xen_drm_front_drm_pipeline {struct xen_drm_front_drm_info *drm_info;int index; + +struct drm_simple_display_pipe pipe; + +struct drm_connector conn; +/* these are only for connector mode checking */ +int width, height; +/* last backend error seen on page flip */ +int pgflip_last_error; };struct xen_drm_front_drm_info {@@ -35,6 +45,8 @@ struct xen_drm_front_drm_info {struct xen_drm_front_ops *front_ops;struct drm_device *drm_dev;struct xen_drm_front_cfg *cfg; + +struct xen_drm_front_drm_pipeline pipeline[XEN_DRM_FRONT_MAX_CRTCS ]; }; static inline uint64_t xen_drm_front_fb_to_cookie(drivers/gpu/drm/xen/xen_drm_front_kms.c new file +106
-0@@ -0,0 +1,299 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include "xen_drm_front_kms.h" + +#include <drm/drmP.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_gem.h> +#include <drm/drm_gem_framebuffer_helper.h> + +#include "xen_drm_front.h" +#include "xen_drm_front_conn.h" +#include "xen_drm_front_drv.h" + +static struct xen_drm_front_drm_pipeline * +to_xen_drm_pipeline (struct drm_simple_display_pipe *pipe) +{ + return container_of(pipe, struct xen_drm_front_drm_pipeline, pipe); +} + +static void fb_destroy (struct drm_framebuffer *fb) +{ +struct xen_drm_front_drm_info *drm_info = fb->dev->dev_private; + + drm_info->front_ops->fb_detach (drm_info->front_info, +xen_drm_front_fb_to_cookie (fb)); +drm_gem_fb_destroy (fb); +} + +static struct drm_framebuffer_funcs fb_funcs = { + .destroy = fb_destroy, +}; + +static struct drm_framebuffer *fb_create (struct drm_device *dev, +struct drm_file *filp,const struct drm_mode_fb_cmd2 *mode_cmd) +{ +struct xen_drm_front_drm_info *drm_info = dev->dev_private; +static struct drm_framebuffer *fb; +struct drm_gem_object *gem_obj; +int ret; + + fb =drm_gem_fb_create_with_funcs (dev, filp, mode_cmd, &fb_funcs); +if (IS_ERR_OR_NULL (fb)) +return fb; + + gem_obj =drm_gem_object_lookup (filp, mode_cmd->handles[0 ]); +if (!gem_obj) { +DRM_ERROR ("Failed to lookup GEM object\n" ); + ret = -ENOENT ; + goto fail; + } + +drm_gem_object_unreference_unlocked (gem_obj); + + ret = drm_info->front_ops->fb_attach ( + drm_info->front_info, +xen_drm_front_dbuf_to_cookie (gem_obj), +xen_drm_front_fb_to_cookie (fb), + fb->width, fb->height, fb->format->format); +if (ret <0 ) { +DRM_ERROR ("Back failed to attach FB %p: %d\n" , fb, ret); + goto fail; + } + +return fb; + +fail: +drm_gem_fb_destroy (fb); +return ERR_PTR (ret); +} + +static const struct drm_mode_config_funcs mode_config_funcs = { + .fb_create = fb_create, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +static int display_set_config (struct drm_simple_display_pipe *pipe, +struct drm_framebuffer *fb) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe); +struct drm_crtc *crtc = &pipe->crtc; +struct xen_drm_front_drm_info *drm_info = pipeline->drm_info; +int ret; + +if (fb) + ret = drm_info->front_ops->mode_set(pipeline, + crtc->x, crtc->y, + fb->width, fb->height, fb->format->cpp[0] * 8,Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c line 111
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +5
-0+ xen_drm_front_fb_to_cookie(fb)); + else + ret = drm_info->front_ops->mode_set (pipeline, +0 ,0 ,0 ,0 ,0 , +xen_drm_front_fb_to_cookie (NULL ));This is a bit much layering, the if (fb) case corresponds to the display_enable/disable hooks, pls fold that in instead of the indirection. simple helpers guarantee that when the display is on, then you have an fb.
Quoted 9 lines
1. Ok, the only reason for having this function was to keep
front_ops->mode_setcalls at one place (will be refactored to be a direct call, not viafront_ops).
2. The if (fb) check was meant not to check if simple helpers may give us some wrong value when we do not expect: there is nothing wrong with them. The check was for 2 cases when this function was called: with fb != NULL on display enable and with fb == NULL on display disable, e.g. fb was used as a flag in this check.Yeah that's what I meant - it is needlessly confusing: You get 2 explicit enable/disable callbacks, then you squash them into 1 function call, only to require an
if (do_I_need_to_enable_or_disable) { /* code that really should be directly put in the enable callback */ } else { /* code that really should be directly put in the enable callback */ }Just a bit of indirection where I didnt' see the point.
Quoted 8 lines
Aside for why this matters: When refactoring the entire subsystem you need to be able to quickly understand how all the drivers work in a specific case, without being an expert on that driver. If there's very little indirection between the shared drm concepts/structs/callbacks and the actual driver code, then that's easy. If there's a bunch of callback layers or indirections like the above, you make subsystem refactoring harder for no reason. And in upstream we optimize for the overall subsystem, not individual drivers.
ok, does make sense, will rework without yet another function
Quoted 59 lines
Quoted 59 lines
3. I will remove this function at all and will make direct calls to the backend on .display_{enable|disable}
Quoted 2 lines
Maybe we need to fix the docs, pls check and if that's not clear, submit a kernel-doc patch for the simple pipe helpers.
no, nothing wrong here, just see my reasoning above
Quoted 9 lines
Quoted 9 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +9
-0+ +if (ret) +DRM_ERROR ("Failed to set mode to back: %d\n" , ret); + +return ret; +} + +static void display_enable (struct drm_simple_display_pipe *pipe, +struct drm_crtc_state *crtc_state)Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c line 126
Quoted 6 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +6
-0+{ +struct drm_crtc *crtc = &pipe->crtc; +struct drm_framebuffer *fb = pipe->plane.state->fb; + +if (display_set_config (pipe, fb) ==0 ) +drm_crtc_vblank_on (crtc);I get the impression your driver doesn't support vblanks (the page flip code at least looks like it's only generating a single event),
yes, this is true
Quoted 2 lines
you also
don't have a enable/disable_vblank implementation.this is because with my previous patches [1] these are now handled by simple helpers, so no need to provide dummy ones in the driver
Quoted 2 lines
If there's no vblank
handling then this shouldn't be needed.yes, I will rework the code, please see below
Quoted 29 lines
Quoted 16 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +16
-0+else +DRM_ERROR ("Failed to enable display\n" ); +} + +static void display_disable (struct drm_simple_display_pipe *pipe) +{ +struct drm_crtc *crtc = &pipe->crtc; + +display_set_config (pipe,NULL ); +drm_crtc_vblank_off (crtc); +/* final check for stalled events */ +if (crtc->state->event && !crtc->state->active) { +unsigned long flags; + +spin_lock_irqsave (&crtc->dev->event_lock, flags); +drm_crtc_send_vblank_event (crtc, crtc->state->event);drivers/gpu/drm/xen/xen_drm_front_kms.c line 152
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +10
-0+spin_unlock_irqrestore (&crtc->dev->event_lock, flags); + crtc->state->event =NULL ; + } +} + +void xen_drm_front_kms_on_frame_done ( +struct xen_drm_front_drm_pipeline *pipeline, +uint64_t fb_cookie) +{ +drm_crtc_handle_vblank (&pipeline->pipe.crtc);Hm, again this doesn't look like real vblank, but only a page-flip done event. If that's correct then please don't use the vblank machinery, but just store the event internally (protected with your own private spinlock)
Quoted 4 lines
Quoted 3 lines
Why can't I use
&dev->event_lock? Anyways for handling page-flip events I will need to lock on it, so I can dodrm_crtc_send_vblank_event?Yeah you can reuse the
event_locktoo, that's what many drivers do.
I just was clarifying on the need for my own private lock ;)
Quoted 79 lines
Quoted 79 lines
Quoted 3 lines
and send it out using
drm_crtc_send_vblank_eventdirectly. No calls toarm_vblank_eventor any of the other vblank infrastructure should be needed.will re-work, e.g. will store
drm_pending_vblank_eventon .display_update and send out on page flip event from the backendQuoted 3 lines
Also please remove the
drm_vblank_init()call, since your hw doesn't really have vblanks. And exposing vblanks to userspace without implementing them is confusing.will remove all vblank handling at all with the re-work above
Quoted 50 lines
Quoted 50 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +50
-0+} + +static void display_send_page_flip (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *old_plane_state) +{ +struct drm_plane_state *plane_state =drm_atomic_get_new_plane_state ( + old_plane_state->state, &pipe->plane); + +/* +* If old_plane_state->fb is NULL and plane_state->fb is not, +* then this is an atomic commit which will enable display. +* If old_plane_state->fb is not NULL and plane_state->fb is, +* then this is an atomic commit which will disable display. +* Ignore these and do not send page flip as this framebuffer will be +* sent to the backend as a part of display_set_config call. +*/ +if (old_plane_state->fb && plane_state->fb) { +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe); +struct xen_drm_front_drm_info *drm_info = pipeline->drm_info; +int ret; + + ret = drm_info->front_ops->page_flip (drm_info->front_info, + pipeline->index, +xen_drm_front_fb_to_cookie (plane_state->fb)); + pipeline->pgflip_last_error = ret; +if (ret) { +DRM_ERROR ("Failed to send page flip request to backend: %d\n" , ret); +/* +* As we are at commit stage the DRM core will anyways +* wait for the vblank and knows nothing about our +* failure. The best we can do is to handle +* vblank now, so there is no vblank/flip_done +* time outs +*/ +drm_crtc_handle_vblank (&pipeline->pipe.crtc); + } + } +} + +static int display_prepare_fb (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *plane_state) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe); + +if (pipeline->pgflip_last_error) { +int ret; + +/* if previous page flip didn't succeed then report the error */ Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c line 207
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +5
-0+ ret = pipeline->pgflip_last_error; +/* and let us try to page flip next time */ + pipeline->pgflip_last_error =0 ; +return ret; + }Nope, this isn't how the uapi works. If your flips fail then we might need to add some error status thing to the drm events, but you can't make the next flip fail.
Well, yes, there is no way for me to tell that the page flip has failed, so this is why I tried to do this workaround with the next page-flip. The reason for that is that if, for example, we are disconnected from the backend for some reason, there is no way for me to tell the user-space that hey, please, do not send any other page flips. If backend can recover and that was a one time error then yes, the code I have will do wrong thing (fail the current page flip), but if the error state is persistent then I will be able to tell the user-space to stop by returning errors. This is kind of trade-off which I am not sure how to solve correctly.
Quoted 6 lines
Quoted 1 line
Do you think I can remove this workaround completely?
Yes. If you want to tell userspace that the backend is gone, send a hotplug uevent and update the connector status to disconnected. Hotplug uevents is how we tell userspace about asynchronous changes. We also have special stuff to signal display cable issue that might require picking a lower resolution (DP link training) and when HDCP encryption failed.
Ah, then I'll need to plumb in connector hotplug machinery. Will add that so I can report errors
Quoted 3 lines
Sending back random errors on pageflips just confuses the compositor, and all correctly working compositors will listen to hotplug events and reprobe all the outputs and change the configuration if necessary.
Good point, thank you
Quoted 144 lines
-Daniel
Quoted 142 lines
Quoted 133 lines
-Daniel
Quoted 131 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +92
-0+return drm_gem_fb_prepare_fb (&pipe->plane, plane_state); +} + +static void display_update (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *old_plane_state) +{ +struct drm_crtc *crtc = &pipe->crtc; +struct drm_pending_vblank_event *event; + + event = crtc->state->event; +if (event) { +struct drm_device *dev = crtc->dev; +unsigned long flags; + + crtc->state->event =NULL ; + +spin_lock_irqsave (&dev->event_lock, flags); +if (drm_crtc_vblank_get (crtc) ==0 ) +drm_crtc_arm_vblank_event (crtc, event); +else +drm_crtc_send_vblank_event (crtc, event); +spin_unlock_irqrestore (&dev->event_lock, flags); + } +/* +* Send page flip request to the backend *after* we have event armed/ +* sent above, so on page flip done event from the backend we can +* deliver it while handling vblank. +*/ +display_send_page_flip (pipe, old_plane_state); +} + +static const struct drm_simple_display_pipe_funcs display_funcs = { + .enable = display_enable, + .disable = display_disable, + .prepare_fb = display_prepare_fb, + .update = display_update, +}; + +static int display_pipe_init (struct xen_drm_front_drm_info *drm_info, +int index,struct xen_drm_front_cfg_connector *cfg, +struct xen_drm_front_drm_pipeline *pipeline) +{ +struct drm_device *dev = drm_info->drm_dev; +const uint32_t *formats; +int format_count; +int ret; + + pipeline->drm_info = drm_info; + pipeline->index = index; + pipeline->height = cfg->height; + pipeline->width = cfg->width; + + ret =xen_drm_front_conn_init (drm_info, &pipeline->conn); +if (ret) +return ret; + + formats =xen_drm_front_conn_get_formats (&format_count); + +return drm_simple_display_pipe_init (dev, &pipeline->pipe, + &display_funcs, formats, format_count, +NULL , &pipeline->conn); +} + +int xen_drm_front_kms_init (struct xen_drm_front_drm_info *drm_info) +{ +struct drm_device *dev = drm_info->drm_dev; +int i, ret; + +drm_mode_config_init (dev); + + dev->mode_config.min_width =0 ; + dev->mode_config.min_height =0 ; + dev->mode_config.max_width =4095 ; + dev->mode_config.max_height =2047 ; + dev->mode_config.funcs = &mode_config_funcs; + +for (i =0 ; i < drm_info->cfg->num_connectors; i++) { +struct xen_drm_front_cfg_connector *cfg = + &drm_info->cfg->connectors[i]; +struct xen_drm_front_drm_pipeline *pipeline = + &drm_info->pipeline[i]; + + ret =display_pipe_init (drm_info, i, cfg, pipeline); +if (ret) { +drm_mode_config_cleanup (dev); +return ret; + } + } + +drm_mode_config_reset (dev); +return 0 ; +}drivers/gpu/drm/xen/xen_drm_front_kms.h new file +30
-0@@ -0,0 +1,30 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_KMS_H_ +#define __XEN_DRM_FRONT_KMS_H_ + +#include "xen_drm_front_drv.h" + +int xen_drm_front_kms_init (struct xen_drm_front_drm_info *drm_info); + +void xen_drm_front_kms_on_frame_done ( +struct xen_drm_front_drm_pipeline *pipeline, +uint64_t fb_cookie); + +#endif /* __XEN_DRM_FRONT_KMS_H_ */ Signature · 1 line
2.7.4Quoted 4 lines
Quoted 4 lines
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel[1] https://patchwork.kernel.org/patch/10211997/
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 7/9] drm/xen-front: Implement KMS/connector handling
In reply to Daniel VetterQuoted 448 lines · Daniel Vetter
Quoted 426 lines · Oleksandr Andrushchenko
Quoted 26 lines · Daniel Vetter
Quoted 25 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Implement kernel modesetiing/connector handling using DRM simple KMS helper pipeline:
- implement KMS part of the driver with the help of DRM simple pipepline helper which is possible due to the fact that the para-virtualized driver only supports a single (primary) plane:
- initialize connectors according to XenStore configuration
- handle frame done events from the backend
- generate vblank events
- create and destroy frame buffers and propagate those to the backend
- propagate set/reset mode configuration to the backend on display enable/disable callbacks
- send page flip request to the backend and implement logic for reporting backend IO errors on prepare fb callback- implement virtual connector handling:
- support only pixel formats suitable for single plane modes
- make sure the connector is always connected
- support a single video mode as per para-virtualized driver configurationQuoted 3 lines
Quoted 1 line
Signed-off-by Oleksandr Andrushchenko <[email protected]>I think once you've removed the midlayer in the previous patch it would makes sense to merge the 2 patches into 1.
ok, will squash the two
Quoted 387 lines
Bunch more comments below.
-DanielQuoted 384 lines
--- drivers/gpu/drm/xen/Makefile | 2 + drivers/gpu/drm/xen/xen_drm_front_conn.c | 125 +++++++++++++ drivers/gpu/drm/xen/xen_drm_front_conn.h | 35 ++++ drivers/gpu/drm/xen/xen_drm_front_drv.c | 15 ++ drivers/gpu/drm/xen/xen_drm_front_drv.h | 12 ++ drivers/gpu/drm/xen/xen_drm_front_kms.c | 299 +++++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_kms.h | 30 ++++ 7 files changed, 518 insertions(+)create mode 100644
drivers/gpu/drm/xen/xen_drm_front_conn.ccreate mode 100644drivers/gpu/drm/xen/xen_drm_front_conn.hcreate mode 100644drivers/gpu/drm/xen/xen_drm_front_kms.ccreate mode 100644drivers/gpu/drm/xen/xen_drm_front_kms.hdrivers/gpu/drm/xen/Makefile +2
-0@@ -2,6 +2,8 @@ drm_xen_front-objs := xen_drm_front.o \ xen_drm_front_drv.o \ + xen_drm_front_kms.o \ + xen_drm_front_conn.o \ xen_drm_front_evtchnl.o \ xen_drm_front_shbuf.o \ xen_drm_front_cfg.odrivers/gpu/drm/xen/xen_drm_front_conn.c new file +125
-0@@ -0,0 +1,125 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_crtc_helper.h> + +#include <video/videomode.h> + +#include "xen_drm_front_conn.h" +#include "xen_drm_front_drv.h" + +static struct xen_drm_front_drm_pipeline * +to_xen_drm_pipeline (struct drm_connector *connector) +{ + return container_of(connector, struct xen_drm_front_drm_pipeline, conn); +} + +static const uint32_t plane_formats[] = { +DRM_FORMAT_RGB565 , +DRM_FORMAT_RGB888 , +DRM_FORMAT_XRGB8888 , +DRM_FORMAT_ARGB8888 , +DRM_FORMAT_XRGB4444 , +DRM_FORMAT_ARGB4444 , +DRM_FORMAT_XRGB1555 , +DRM_FORMAT_ARGB1555 , +}; + +const uint32_t *xen_drm_front_conn_get_formats (int *format_count) +{ + *format_count =ARRAY_SIZE (plane_formats); +return plane_formats; +} + +static enum drm_connector_status connector_detect ( +struct drm_connector *connector,bool force) +{ +if (drm_dev_is_unplugged (connector->dev)) +return connector_status_disconnected; + +return connector_status_connected; +} + +#define XEN_DRM_NUM_VIDEO_MODES 1 +#define XEN_DRM_CRTC_VREFRESH_HZ 60 + +static int connector_get_modes (struct drm_connector *connector) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (connector); +struct drm_display_mode *mode; +struct videomode videomode; +int width, height; + + mode =drm_mode_create (connector->dev); +if (!mode) +return 0 ; + +memset (&videomode,0 ,sizeof (videomode)); + videomode.hactive = pipeline->width; + videomode.vactive = pipeline->height; + width = videomode.hactive + videomode.hfront_porch + + videomode.hback_porch + videomode.hsync_len; + height = videomode.vactive + videomode.vfront_porch + + videomode.vback_porch + videomode.vsync_len; + videomode.pixelclock = width * height *XEN_DRM_CRTC_VREFRESH_HZ ; + mode->type =DRM_MODE_TYPE_PREFERRED |DRM_MODE_TYPE_DRIVER ; + +drm_display_mode_from_videomode (&videomode, mode); +drm_mode_probed_add (connector, mode); +return XEN_DRM_NUM_VIDEO_MODES ; +} + +static int connector_mode_valid (struct drm_connector *connector, +struct drm_display_mode *mode) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (connector); + +if (mode->hdisplay != pipeline->width) +return MODE_ERROR ; + +if (mode->vdisplay != pipeline->height) +return MODE_ERROR ; + +return MODE_OK ; +} + +static const struct drm_connector_helper_funcs connector_helper_funcs = { + .get_modes = connector_get_modes, + .mode_valid = connector_mode_valid, +}; + +static const struct drm_connector_funcs connector_funcs = { + .detect = connector_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +int xen_drm_front_conn_init (struct xen_drm_front_drm_info *drm_info, +struct drm_connector *connector) +{ +drm_connector_helper_add (connector, &connector_helper_funcs); + +return drm_connector_init (drm_info->drm_dev, connector, + &connector_funcs,DRM_MODE_CONNECTOR_VIRTUAL ); +}drivers/gpu/drm/xen/xen_drm_front_conn.h new file +35
-0@@ -0,0 +1,35 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_CONN_H_ +#define __XEN_DRM_FRONT_CONN_H_ + +#include <drm/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_encoder.h> + +#include <linux/wait.h> + +struct xen_drm_front_drm_info ; + +const uint32_t *xen_drm_front_conn_get_formats (int *format_count); + +int xen_drm_front_conn_init (struct xen_drm_front_drm_info *drm_info, +struct drm_connector *connector); + +#endif /* __XEN_DRM_FRONT_CONN_H_ */ drivers/gpu/drm/xen/xen_drm_front_drv.c +15
-0@@ -23,6 +23,7 @@#include "xen_drm_front.h" #include "xen_drm_front_cfg.h" #include "xen_drm_front_drv.h" +#include "xen_drm_front_kms.h" static int dumb_create (struct drm_file *filp,struct drm_device *dev,struct drm_mode_create_dumb *args)@@ -41,6 +42,13 @@ static void free_object(struct drm_gem_object *obj)static void on_frame_done (struct platform_device *pdev,int conn_idx,uint64_t fb_cookie) { +struct xen_drm_front_drm_info *drm_info =platform_get_drvdata (pdev); + +if (unlikely (conn_idx >= drm_info->cfg->num_connectors)) +return ; + +xen_drm_front_kms_on_frame_done (&drm_info->pipeline[conn_idx], + fb_cookie); }static void lastclose (struct drm_device *dev)@@ -157,6 +165,12 @@ int xen_drm_front_drv_probe(struct platform_device *pdev,return ret; } + ret =xen_drm_front_kms_init (drm_info); +if (ret) { +DRM_ERROR ("Failed to initialize DRM/KMS, ret %d\n" , ret); + goto fail_modeset; + } + dev->irq_enabled =1 ; ret =drm_dev_register (dev,0 );@@ -172,6 +186,7 @@ int xen_drm_front_drv_probe(struct platform_device *pdev, fail_register:drm_dev_unregister (dev); +fail_modeset:drm_mode_config_cleanup (dev);return ret; }drivers/gpu/drm/xen/xen_drm_front_drv.h +12
-0@@ -20,14 +20,24 @@#define __XEN_DRM_FRONT_DRV_H_#include <drm/drmP.h> +#include <drm/drm_simple_kms_helper.h> #include "xen_drm_front.h" #include "xen_drm_front_cfg.h" +#include "xen_drm_front_conn.h" struct xen_drm_front_drm_pipeline {struct xen_drm_front_drm_info *drm_info;int index; + +struct drm_simple_display_pipe pipe; + +struct drm_connector conn; +/* these are only for connector mode checking */ +int width, height; +/* last backend error seen on page flip */ +int pgflip_last_error; };struct xen_drm_front_drm_info {@@ -35,6 +45,8 @@ struct xen_drm_front_drm_info {struct xen_drm_front_ops *front_ops;struct drm_device *drm_dev;struct xen_drm_front_cfg *cfg; + +struct xen_drm_front_drm_pipeline pipeline[XEN_DRM_FRONT_MAX_CRTCS ]; }; static inline uint64_t xen_drm_front_fb_to_cookie(drivers/gpu/drm/xen/xen_drm_front_kms.c new file +106
-0@@ -0,0 +1,299 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include "xen_drm_front_kms.h" + +#include <drm/drmP.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_gem.h> +#include <drm/drm_gem_framebuffer_helper.h> + +#include "xen_drm_front.h" +#include "xen_drm_front_conn.h" +#include "xen_drm_front_drv.h" + +static struct xen_drm_front_drm_pipeline * +to_xen_drm_pipeline (struct drm_simple_display_pipe *pipe) +{ + return container_of(pipe, struct xen_drm_front_drm_pipeline, pipe); +} + +static void fb_destroy (struct drm_framebuffer *fb) +{ +struct xen_drm_front_drm_info *drm_info = fb->dev->dev_private; + + drm_info->front_ops->fb_detach (drm_info->front_info, +xen_drm_front_fb_to_cookie (fb)); +drm_gem_fb_destroy (fb); +} + +static struct drm_framebuffer_funcs fb_funcs = { + .destroy = fb_destroy, +}; + +static struct drm_framebuffer *fb_create (struct drm_device *dev, +struct drm_file *filp,const struct drm_mode_fb_cmd2 *mode_cmd) +{ +struct xen_drm_front_drm_info *drm_info = dev->dev_private; +static struct drm_framebuffer *fb; +struct drm_gem_object *gem_obj; +int ret; + + fb =drm_gem_fb_create_with_funcs (dev, filp, mode_cmd, &fb_funcs); +if (IS_ERR_OR_NULL (fb)) +return fb; + + gem_obj =drm_gem_object_lookup (filp, mode_cmd->handles[0 ]); +if (!gem_obj) { +DRM_ERROR ("Failed to lookup GEM object\n" ); + ret = -ENOENT ; + goto fail; + } + +drm_gem_object_unreference_unlocked (gem_obj); + + ret = drm_info->front_ops->fb_attach ( + drm_info->front_info, +xen_drm_front_dbuf_to_cookie (gem_obj), +xen_drm_front_fb_to_cookie (fb), + fb->width, fb->height, fb->format->format); +if (ret <0 ) { +DRM_ERROR ("Back failed to attach FB %p: %d\n" , fb, ret); + goto fail; + } + +return fb; + +fail: +drm_gem_fb_destroy (fb); +return ERR_PTR (ret); +} + +static const struct drm_mode_config_funcs mode_config_funcs = { + .fb_create = fb_create, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +static int display_set_config (struct drm_simple_display_pipe *pipe, +struct drm_framebuffer *fb) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe); +struct drm_crtc *crtc = &pipe->crtc; +struct xen_drm_front_drm_info *drm_info = pipeline->drm_info; +int ret; + +if (fb) + ret = drm_info->front_ops->mode_set(pipeline, + crtc->x, crtc->y, + fb->width, fb->height, fb->format->cpp[0] * 8,Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c line 111
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +5
-0+ xen_drm_front_fb_to_cookie(fb)); + else + ret = drm_info->front_ops->mode_set (pipeline, +0 ,0 ,0 ,0 ,0 , +xen_drm_front_fb_to_cookie (NULL ));This is a bit much layering, the if (fb) case corresponds to the display_enable/disable hooks, pls fold that in instead of the indirection. simple helpers guarantee that when the display is on, then you have an fb.
Quoted 9 lines
1. Ok, the only reason for having this function was to keep
front_ops->mode_setcalls at one place (will be refactored to be a direct call, not viafront_ops).
2. The if (fb) check was meant not to check if simple helpers may give us some wrong value when we do not expect: there is nothing wrong with them. The check was for 2 cases when this function was called: with fb != NULL on display enable and with fb == NULL on display disable, e.g. fb was used as a flag in this check.Yeah that's what I meant - it is needlessly confusing: You get 2 explicit enable/disable callbacks, then you squash them into 1 function call, only to require an
if (do_I_need_to_enable_or_disable) { /* code that really should be directly put in the enable callback */ } else { /* code that really should be directly put in the enable callback */ }Just a bit of indirection where I didnt' see the point.
Quoted 8 lines
Aside for why this matters: When refactoring the entire subsystem you need to be able to quickly understand how all the drivers work in a specific case, without being an expert on that driver. If there's very little indirection between the shared drm concepts/structs/callbacks and the actual driver code, then that's easy. If there's a bunch of callback layers or indirections like the above, you make subsystem refactoring harder for no reason. And in upstream we optimize for the overall subsystem, not individual drivers.
ok, does make sense, will rework without yet another function
Quoted 59 lines
Quoted 59 lines
3. I will remove this function at all and will make direct calls to the backend on .display_{enable|disable}
Quoted 2 lines
Maybe we need to fix the docs, pls check and if that's not clear, submit a kernel-doc patch for the simple pipe helpers.
no, nothing wrong here, just see my reasoning above
Quoted 9 lines
Quoted 9 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +9
-0+ +if (ret) +DRM_ERROR ("Failed to set mode to back: %d\n" , ret); + +return ret; +} + +static void display_enable (struct drm_simple_display_pipe *pipe, +struct drm_crtc_state *crtc_state)Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c line 126
Quoted 6 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +6
-0+{ +struct drm_crtc *crtc = &pipe->crtc; +struct drm_framebuffer *fb = pipe->plane.state->fb; + +if (display_set_config (pipe, fb) ==0 ) +drm_crtc_vblank_on (crtc);I get the impression your driver doesn't support vblanks (the page flip code at least looks like it's only generating a single event),
yes, this is true
Quoted 2 lines
you also
don't have a enable/disable_vblank implementation.this is because with my previous patches [1] these are now handled by simple helpers, so no need to provide dummy ones in the driver
Quoted 2 lines
If there's no vblank
handling then this shouldn't be needed.yes, I will rework the code, please see below
Quoted 29 lines
Quoted 16 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +16
-0+else +DRM_ERROR ("Failed to enable display\n" ); +} + +static void display_disable (struct drm_simple_display_pipe *pipe) +{ +struct drm_crtc *crtc = &pipe->crtc; + +display_set_config (pipe,NULL ); +drm_crtc_vblank_off (crtc); +/* final check for stalled events */ +if (crtc->state->event && !crtc->state->active) { +unsigned long flags; + +spin_lock_irqsave (&crtc->dev->event_lock, flags); +drm_crtc_send_vblank_event (crtc, crtc->state->event);drivers/gpu/drm/xen/xen_drm_front_kms.c line 152
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +10
-0+spin_unlock_irqrestore (&crtc->dev->event_lock, flags); + crtc->state->event =NULL ; + } +} + +void xen_drm_front_kms_on_frame_done ( +struct xen_drm_front_drm_pipeline *pipeline, +uint64_t fb_cookie) +{ +drm_crtc_handle_vblank (&pipeline->pipe.crtc);Hm, again this doesn't look like real vblank, but only a page-flip done event. If that's correct then please don't use the vblank machinery, but just store the event internally (protected with your own private spinlock)
Quoted 4 lines
Quoted 3 lines
Why can't I use
&dev->event_lock? Anyways for handling page-flip events I will need to lock on it, so I can dodrm_crtc_send_vblank_event?Yeah you can reuse the
event_locktoo, that's what many drivers do.
I just was clarifying on the need for my own private lock ;)
Quoted 79 lines
Quoted 79 lines
Quoted 3 lines
and send it out using
drm_crtc_send_vblank_eventdirectly. No calls toarm_vblank_eventor any of the other vblank infrastructure should be needed.will re-work, e.g. will store
drm_pending_vblank_eventon .display_update and send out on page flip event from the backendQuoted 3 lines
Also please remove the
drm_vblank_init()call, since your hw doesn't really have vblanks. And exposing vblanks to userspace without implementing them is confusing.will remove all vblank handling at all with the re-work above
Quoted 50 lines
Quoted 50 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +50
-0+} + +static void display_send_page_flip (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *old_plane_state) +{ +struct drm_plane_state *plane_state =drm_atomic_get_new_plane_state ( + old_plane_state->state, &pipe->plane); + +/* +* If old_plane_state->fb is NULL and plane_state->fb is not, +* then this is an atomic commit which will enable display. +* If old_plane_state->fb is not NULL and plane_state->fb is, +* then this is an atomic commit which will disable display. +* Ignore these and do not send page flip as this framebuffer will be +* sent to the backend as a part of display_set_config call. +*/ +if (old_plane_state->fb && plane_state->fb) { +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe); +struct xen_drm_front_drm_info *drm_info = pipeline->drm_info; +int ret; + + ret = drm_info->front_ops->page_flip (drm_info->front_info, + pipeline->index, +xen_drm_front_fb_to_cookie (plane_state->fb)); + pipeline->pgflip_last_error = ret; +if (ret) { +DRM_ERROR ("Failed to send page flip request to backend: %d\n" , ret); +/* +* As we are at commit stage the DRM core will anyways +* wait for the vblank and knows nothing about our +* failure. The best we can do is to handle +* vblank now, so there is no vblank/flip_done +* time outs +*/ +drm_crtc_handle_vblank (&pipeline->pipe.crtc); + } + } +} + +static int display_prepare_fb (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *plane_state) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe); + +if (pipeline->pgflip_last_error) { +int ret; + +/* if previous page flip didn't succeed then report the error */ Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c line 207
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +5
-0+ ret = pipeline->pgflip_last_error; +/* and let us try to page flip next time */ + pipeline->pgflip_last_error =0 ; +return ret; + }Nope, this isn't how the uapi works. If your flips fail then we might need to add some error status thing to the drm events, but you can't make the next flip fail.
Well, yes, there is no way for me to tell that the page flip has failed, so this is why I tried to do this workaround with the next page-flip. The reason for that is that if, for example, we are disconnected from the backend for some reason, there is no way for me to tell the user-space that hey, please, do not send any other page flips. If backend can recover and that was a one time error then yes, the code I have will do wrong thing (fail the current page flip), but if the error state is persistent then I will be able to tell the user-space to stop by returning errors. This is kind of trade-off which I am not sure how to solve correctly.
Quoted 6 lines
Quoted 1 line
Do you think I can remove this workaround completely?
Yes. If you want to tell userspace that the backend is gone, send a hotplug uevent and update the connector status to disconnected. Hotplug uevents is how we tell userspace about asynchronous changes. We also have special stuff to signal display cable issue that might require picking a lower resolution (DP link training) and when HDCP encryption failed.
Ah, then I'll need to plumb in connector hotplug machinery. Will add that so I can report errors
Quoted 3 lines
Sending back random errors on pageflips just confuses the compositor, and all correctly working compositors will listen to hotplug events and reprobe all the outputs and change the configuration if necessary.
Good point, thank you
Quoted 144 lines
-Daniel
Quoted 142 lines
Quoted 133 lines
-Daniel
Quoted 131 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +92
-0+return drm_gem_fb_prepare_fb (&pipe->plane, plane_state); +} + +static void display_update (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *old_plane_state) +{ +struct drm_crtc *crtc = &pipe->crtc; +struct drm_pending_vblank_event *event; + + event = crtc->state->event; +if (event) { +struct drm_device *dev = crtc->dev; +unsigned long flags; + + crtc->state->event =NULL ; + +spin_lock_irqsave (&dev->event_lock, flags); +if (drm_crtc_vblank_get (crtc) ==0 ) +drm_crtc_arm_vblank_event (crtc, event); +else +drm_crtc_send_vblank_event (crtc, event); +spin_unlock_irqrestore (&dev->event_lock, flags); + } +/* +* Send page flip request to the backend *after* we have event armed/ +* sent above, so on page flip done event from the backend we can +* deliver it while handling vblank. +*/ +display_send_page_flip (pipe, old_plane_state); +} + +static const struct drm_simple_display_pipe_funcs display_funcs = { + .enable = display_enable, + .disable = display_disable, + .prepare_fb = display_prepare_fb, + .update = display_update, +}; + +static int display_pipe_init (struct xen_drm_front_drm_info *drm_info, +int index,struct xen_drm_front_cfg_connector *cfg, +struct xen_drm_front_drm_pipeline *pipeline) +{ +struct drm_device *dev = drm_info->drm_dev; +const uint32_t *formats; +int format_count; +int ret; + + pipeline->drm_info = drm_info; + pipeline->index = index; + pipeline->height = cfg->height; + pipeline->width = cfg->width; + + ret =xen_drm_front_conn_init (drm_info, &pipeline->conn); +if (ret) +return ret; + + formats =xen_drm_front_conn_get_formats (&format_count); + +return drm_simple_display_pipe_init (dev, &pipeline->pipe, + &display_funcs, formats, format_count, +NULL , &pipeline->conn); +} + +int xen_drm_front_kms_init (struct xen_drm_front_drm_info *drm_info) +{ +struct drm_device *dev = drm_info->drm_dev; +int i, ret; + +drm_mode_config_init (dev); + + dev->mode_config.min_width =0 ; + dev->mode_config.min_height =0 ; + dev->mode_config.max_width =4095 ; + dev->mode_config.max_height =2047 ; + dev->mode_config.funcs = &mode_config_funcs; + +for (i =0 ; i < drm_info->cfg->num_connectors; i++) { +struct xen_drm_front_cfg_connector *cfg = + &drm_info->cfg->connectors[i]; +struct xen_drm_front_drm_pipeline *pipeline = + &drm_info->pipeline[i]; + + ret =display_pipe_init (drm_info, i, cfg, pipeline); +if (ret) { +drm_mode_config_cleanup (dev); +return ret; + } + } + +drm_mode_config_reset (dev); +return 0 ; +}drivers/gpu/drm/xen/xen_drm_front_kms.h new file +30
-0@@ -0,0 +1,30 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_KMS_H_ +#define __XEN_DRM_FRONT_KMS_H_ + +#include "xen_drm_front_drv.h" + +int xen_drm_front_kms_init (struct xen_drm_front_drm_info *drm_info); + +void xen_drm_front_kms_on_frame_done ( +struct xen_drm_front_drm_pipeline *pipeline, +uint64_t fb_cookie); + +#endif /* __XEN_DRM_FRONT_KMS_H_ */ Signature · 1 line
2.7.4Quoted 4 lines
Quoted 4 lines
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel[1] https://patchwork.kernel.org/patch/10211997/
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Re: [PATCH 7/9] drm/xen-front: Implement KMS/connector handling
In reply to Oleksandr AndrushchenkoQuoted 427 lines · Oleksandr Andrushchenko
Quoted 26 lines · Daniel Vetter
Quoted 25 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Implement kernel modesetiing/connector handling using DRM simple KMS helper pipeline:
- implement KMS part of the driver with the help of DRM simple pipepline helper which is possible due to the fact that the para-virtualized driver only supports a single (primary) plane:
- initialize connectors according to XenStore configuration
- handle frame done events from the backend
- generate vblank events
- create and destroy frame buffers and propagate those to the backend
- propagate set/reset mode configuration to the backend on display enable/disable callbacks
- send page flip request to the backend and implement logic for reporting backend IO errors on prepare fb callback- implement virtual connector handling:
- support only pixel formats suitable for single plane modes
- make sure the connector is always connected
- support a single video mode as per para-virtualized driver configurationQuoted 3 lines
Quoted 1 line
Signed-off-by Oleksandr Andrushchenko <[email protected]>I think once you've removed the midlayer in the previous patch it would makes sense to merge the 2 patches into 1.
ok, will squash the two
Quoted 388 lines
Bunch more comments below.
-DanielQuoted 384 lines
--- drivers/gpu/drm/xen/Makefile | 2 + drivers/gpu/drm/xen/xen_drm_front_conn.c | 125 +++++++++++++ drivers/gpu/drm/xen/xen_drm_front_conn.h | 35 ++++ drivers/gpu/drm/xen/xen_drm_front_drv.c | 15 ++ drivers/gpu/drm/xen/xen_drm_front_drv.h | 12 ++ drivers/gpu/drm/xen/xen_drm_front_kms.c | 299 +++++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_kms.h | 30 ++++ 7 files changed, 518 insertions(+)create mode 100644
drivers/gpu/drm/xen/xen_drm_front_conn.ccreate mode 100644drivers/gpu/drm/xen/xen_drm_front_conn.hcreate mode 100644drivers/gpu/drm/xen/xen_drm_front_kms.ccreate mode 100644drivers/gpu/drm/xen/xen_drm_front_kms.hdrivers/gpu/drm/xen/Makefile +2
-0@@ -2,6 +2,8 @@ drm_xen_front-objs := xen_drm_front.o \ xen_drm_front_drv.o \ + xen_drm_front_kms.o \ + xen_drm_front_conn.o \ xen_drm_front_evtchnl.o \ xen_drm_front_shbuf.o \ xen_drm_front_cfg.odrivers/gpu/drm/xen/xen_drm_front_conn.c new file +125
-0@@ -0,0 +1,125 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_crtc_helper.h> + +#include <video/videomode.h> + +#include "xen_drm_front_conn.h" +#include "xen_drm_front_drv.h" + +static struct xen_drm_front_drm_pipeline * +to_xen_drm_pipeline (struct drm_connector *connector) +{ + return container_of(connector, struct xen_drm_front_drm_pipeline, conn); +} + +static const uint32_t plane_formats[] = { +DRM_FORMAT_RGB565 , +DRM_FORMAT_RGB888 , +DRM_FORMAT_XRGB8888 , +DRM_FORMAT_ARGB8888 , +DRM_FORMAT_XRGB4444 , +DRM_FORMAT_ARGB4444 , +DRM_FORMAT_XRGB1555 , +DRM_FORMAT_ARGB1555 , +}; + +const uint32_t *xen_drm_front_conn_get_formats (int *format_count) +{ + *format_count =ARRAY_SIZE (plane_formats); +return plane_formats; +} + +static enum drm_connector_status connector_detect ( +struct drm_connector *connector,bool force) +{ +if (drm_dev_is_unplugged (connector->dev)) +return connector_status_disconnected; + +return connector_status_connected; +} + +#define XEN_DRM_NUM_VIDEO_MODES 1 +#define XEN_DRM_CRTC_VREFRESH_HZ 60 + +static int connector_get_modes (struct drm_connector *connector) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (connector); +struct drm_display_mode *mode; +struct videomode videomode; +int width, height; + + mode =drm_mode_create (connector->dev); +if (!mode) +return 0 ; + +memset (&videomode,0 ,sizeof (videomode)); + videomode.hactive = pipeline->width; + videomode.vactive = pipeline->height; + width = videomode.hactive + videomode.hfront_porch + + videomode.hback_porch + videomode.hsync_len; + height = videomode.vactive + videomode.vfront_porch + + videomode.vback_porch + videomode.vsync_len; + videomode.pixelclock = width * height *XEN_DRM_CRTC_VREFRESH_HZ ; + mode->type =DRM_MODE_TYPE_PREFERRED |DRM_MODE_TYPE_DRIVER ; + +drm_display_mode_from_videomode (&videomode, mode); +drm_mode_probed_add (connector, mode); +return XEN_DRM_NUM_VIDEO_MODES ; +} + +static int connector_mode_valid (struct drm_connector *connector, +struct drm_display_mode *mode) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (connector); + +if (mode->hdisplay != pipeline->width) +return MODE_ERROR ; + +if (mode->vdisplay != pipeline->height) +return MODE_ERROR ; + +return MODE_OK ; +} + +static const struct drm_connector_helper_funcs connector_helper_funcs = { + .get_modes = connector_get_modes, + .mode_valid = connector_mode_valid, +}; + +static const struct drm_connector_funcs connector_funcs = { + .detect = connector_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +int xen_drm_front_conn_init (struct xen_drm_front_drm_info *drm_info, +struct drm_connector *connector) +{ +drm_connector_helper_add (connector, &connector_helper_funcs); + +return drm_connector_init (drm_info->drm_dev, connector, + &connector_funcs,DRM_MODE_CONNECTOR_VIRTUAL ); +}drivers/gpu/drm/xen/xen_drm_front_conn.h new file +35
-0@@ -0,0 +1,35 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_CONN_H_ +#define __XEN_DRM_FRONT_CONN_H_ + +#include <drm/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_encoder.h> + +#include <linux/wait.h> + +struct xen_drm_front_drm_info ; + +const uint32_t *xen_drm_front_conn_get_formats (int *format_count); + +int xen_drm_front_conn_init (struct xen_drm_front_drm_info *drm_info, +struct drm_connector *connector); + +#endif /* __XEN_DRM_FRONT_CONN_H_ */ drivers/gpu/drm/xen/xen_drm_front_drv.c +15
-0@@ -23,6 +23,7 @@#include "xen_drm_front.h" #include "xen_drm_front_cfg.h" #include "xen_drm_front_drv.h" +#include "xen_drm_front_kms.h" static int dumb_create (struct drm_file *filp,struct drm_device *dev,struct drm_mode_create_dumb *args)@@ -41,6 +42,13 @@ static void free_object(struct drm_gem_object *obj)static void on_frame_done (struct platform_device *pdev,int conn_idx,uint64_t fb_cookie) { +struct xen_drm_front_drm_info *drm_info =platform_get_drvdata (pdev); + +if (unlikely (conn_idx >= drm_info->cfg->num_connectors)) +return ; + +xen_drm_front_kms_on_frame_done (&drm_info->pipeline[conn_idx], + fb_cookie); }static void lastclose (struct drm_device *dev)@@ -157,6 +165,12 @@ int xen_drm_front_drv_probe(struct platform_device *pdev,return ret; } + ret =xen_drm_front_kms_init (drm_info); +if (ret) { +DRM_ERROR ("Failed to initialize DRM/KMS, ret %d\n" , ret); + goto fail_modeset; + } + dev->irq_enabled =1 ; ret =drm_dev_register (dev,0 );@@ -172,6 +186,7 @@ int xen_drm_front_drv_probe(struct platform_device *pdev, fail_register:drm_dev_unregister (dev); +fail_modeset:drm_mode_config_cleanup (dev);return ret; }drivers/gpu/drm/xen/xen_drm_front_drv.h +12
-0@@ -20,14 +20,24 @@#define __XEN_DRM_FRONT_DRV_H_#include <drm/drmP.h> +#include <drm/drm_simple_kms_helper.h> #include "xen_drm_front.h" #include "xen_drm_front_cfg.h" +#include "xen_drm_front_conn.h" struct xen_drm_front_drm_pipeline {struct xen_drm_front_drm_info *drm_info;int index; + +struct drm_simple_display_pipe pipe; + +struct drm_connector conn; +/* these are only for connector mode checking */ +int width, height; +/* last backend error seen on page flip */ +int pgflip_last_error; };struct xen_drm_front_drm_info {@@ -35,6 +45,8 @@ struct xen_drm_front_drm_info {struct xen_drm_front_ops *front_ops;struct drm_device *drm_dev;struct xen_drm_front_cfg *cfg; + +struct xen_drm_front_drm_pipeline pipeline[XEN_DRM_FRONT_MAX_CRTCS ]; }; static inline uint64_t xen_drm_front_fb_to_cookie(drivers/gpu/drm/xen/xen_drm_front_kms.c new file +106
-0@@ -0,0 +1,299 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include "xen_drm_front_kms.h" + +#include <drm/drmP.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_gem.h> +#include <drm/drm_gem_framebuffer_helper.h> + +#include "xen_drm_front.h" +#include "xen_drm_front_conn.h" +#include "xen_drm_front_drv.h" + +static struct xen_drm_front_drm_pipeline * +to_xen_drm_pipeline (struct drm_simple_display_pipe *pipe) +{ + return container_of(pipe, struct xen_drm_front_drm_pipeline, pipe); +} + +static void fb_destroy (struct drm_framebuffer *fb) +{ +struct xen_drm_front_drm_info *drm_info = fb->dev->dev_private; + + drm_info->front_ops->fb_detach (drm_info->front_info, +xen_drm_front_fb_to_cookie (fb)); +drm_gem_fb_destroy (fb); +} + +static struct drm_framebuffer_funcs fb_funcs = { + .destroy = fb_destroy, +}; + +static struct drm_framebuffer *fb_create (struct drm_device *dev, +struct drm_file *filp,const struct drm_mode_fb_cmd2 *mode_cmd) +{ +struct xen_drm_front_drm_info *drm_info = dev->dev_private; +static struct drm_framebuffer *fb; +struct drm_gem_object *gem_obj; +int ret; + + fb =drm_gem_fb_create_with_funcs (dev, filp, mode_cmd, &fb_funcs); +if (IS_ERR_OR_NULL (fb)) +return fb; + + gem_obj =drm_gem_object_lookup (filp, mode_cmd->handles[0 ]); +if (!gem_obj) { +DRM_ERROR ("Failed to lookup GEM object\n" ); + ret = -ENOENT ; + goto fail; + } + +drm_gem_object_unreference_unlocked (gem_obj); + + ret = drm_info->front_ops->fb_attach ( + drm_info->front_info, +xen_drm_front_dbuf_to_cookie (gem_obj), +xen_drm_front_fb_to_cookie (fb), + fb->width, fb->height, fb->format->format); +if (ret <0 ) { +DRM_ERROR ("Back failed to attach FB %p: %d\n" , fb, ret); + goto fail; + } + +return fb; + +fail: +drm_gem_fb_destroy (fb); +return ERR_PTR (ret); +} + +static const struct drm_mode_config_funcs mode_config_funcs = { + .fb_create = fb_create, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +static int display_set_config (struct drm_simple_display_pipe *pipe, +struct drm_framebuffer *fb) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe); +struct drm_crtc *crtc = &pipe->crtc; +struct xen_drm_front_drm_info *drm_info = pipeline->drm_info; +int ret; + +if (fb) + ret = drm_info->front_ops->mode_set(pipeline, + crtc->x, crtc->y, + fb->width, fb->height, fb->format->cpp[0] * 8,Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c line 111
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +5
-0+ xen_drm_front_fb_to_cookie(fb)); + else + ret = drm_info->front_ops->mode_set (pipeline, +0 ,0 ,0 ,0 ,0 , +xen_drm_front_fb_to_cookie (NULL ));This is a bit much layering, the if (fb) case corresponds to the display_enable/disable hooks, pls fold that in instead of the indirection. simple helpers guarantee that when the display is on, then you have an fb.
Quoted 9 lines
1. Ok, the only reason for having this function was to keep
front_ops->mode_setcalls at one place (will be refactored to be a direct call, not viafront_ops).
2. The if (fb) check was meant not to check if simple helpers may give us some wrong value when we do not expect: there is nothing wrong with them. The check was for 2 cases when this function was called: with fb != NULL on display enable and with fb == NULL on display disable, e.g. fb was used as a flag in this check.
Yeah that's what I meant - it is needlessly confusing: You get 2 explicit enable/disable callbacks, then you squash them into 1 function call, only to require an
if (do_I_need_to_enable_or_disable) {
/* code that really should be directly put in the enable callback */
} else {
/* code that really should be directly put in the enable callback */
}Just a bit of indirection where I didnt' see the point.
Aside for why this matters: When refactoring the entire subsystem you need to be able to quickly understand how all the drivers work in a specific case, without being an expert on that driver. If there's very little indirection between the shared drm concepts/structs/callbacks and the actual driver code, then that's easy. If there's a bunch of callback layers or indirections like the above, you make subsystem refactoring harder for no reason. And in upstream we optimize for the overall subsystem, not individual drivers.
Quoted 60 lines
3. I will remove this function at all and will make direct calls to the backend on .display_{enable|disable}
Quoted 3 lines
Maybe we need to fix the docs, pls check and if that's not clear, submit a kernel-doc patch for the simple pipe helpers.
no, nothing wrong here, just see my reasoning above
Quoted 9 lines
Quoted 9 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +9
-0+ +if (ret) +DRM_ERROR ("Failed to set mode to back: %d\n" , ret); + +return ret; +} + +static void display_enable (struct drm_simple_display_pipe *pipe, +struct drm_crtc_state *crtc_state)Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c line 126
Quoted 6 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +6
-0+{ +struct drm_crtc *crtc = &pipe->crtc; +struct drm_framebuffer *fb = pipe->plane.state->fb; + +if (display_set_config (pipe, fb) ==0 ) +drm_crtc_vblank_on (crtc);I get the impression your driver doesn't support vblanks (the page flip code at least looks like it's only generating a single event),
yes, this is true
Quoted 2 lines
you also
don't have a enable/disable_vblank implementation.this is because with my previous patches [1] these are now handled by simple helpers, so no need to provide dummy ones in the driver
Quoted 2 lines
If there's no vblank
handling then this shouldn't be needed.yes, I will rework the code, please see below
Quoted 21 lines
Quoted 21 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +21
-0+else +DRM_ERROR ("Failed to enable display\n" ); +} + +static void display_disable (struct drm_simple_display_pipe *pipe) +{ +struct drm_crtc *crtc = &pipe->crtc; + +display_set_config (pipe,NULL ); +drm_crtc_vblank_off (crtc); +/* final check for stalled events */ +if (crtc->state->event && !crtc->state->active) { +unsigned long flags; + +spin_lock_irqsave (&crtc->dev->event_lock, flags); +drm_crtc_send_vblank_event (crtc, crtc->state->event); +spin_unlock_irqrestore (&crtc->dev->event_lock, flags); + crtc->state->event =NULL ; + } +} +Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c line 152
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +5
-0+void xen_drm_front_kms_on_frame_done ( +struct xen_drm_front_drm_pipeline *pipeline, +uint64_t fb_cookie) +{ +drm_crtc_handle_vblank (&pipeline->pipe.crtc);Hm, again this doesn't look like real vblank, but only a page-flip done event. If that's correct then please don't use the vblank machinery, but just store the event internally (protected with your own private spinlock)
Quoted 3 lines
Why can't I use
&dev->event_lock? Anyways for handling page-flip events I will need to lock on it, so I can dodrm_crtc_send_vblank_event?
Yeah you can reuse the event_lock too, that's what many drivers do.
Quoted 80 lines
Quoted 3 lines
and send it out using
drm_crtc_send_vblank_eventdirectly. No calls toarm_vblank_eventor any of the other vblank infrastructure should be needed.will re-work, e.g. will store
drm_pending_vblank_eventon .display_update and send out on page flip event from the backendQuoted 3 lines
Also please remove the
drm_vblank_init()call, since your hw doesn't really have vblanks. And exposing vblanks to userspace without implementing them is confusing.will remove all vblank handling at all with the re-work above
Quoted 51 lines
Quoted 51 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +50
-0+} + +static void display_send_page_flip (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *old_plane_state) +{ +struct drm_plane_state *plane_state =drm_atomic_get_new_plane_state ( + old_plane_state->state, &pipe->plane); + +/* +* If old_plane_state->fb is NULL and plane_state->fb is not, +* then this is an atomic commit which will enable display. +* If old_plane_state->fb is not NULL and plane_state->fb is, +* then this is an atomic commit which will disable display. +* Ignore these and do not send page flip as this framebuffer will be +* sent to the backend as a part of display_set_config call. +*/ +if (old_plane_state->fb && plane_state->fb) { +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe); +struct xen_drm_front_drm_info *drm_info = pipeline->drm_info; +int ret; + + ret = drm_info->front_ops->page_flip (drm_info->front_info, + pipeline->index, +xen_drm_front_fb_to_cookie (plane_state->fb)); + pipeline->pgflip_last_error = ret; +if (ret) { +DRM_ERROR ("Failed to send page flip request to backend: %d\n" , ret); +/* +* As we are at commit stage the DRM core will anyways +* wait for the vblank and knows nothing about our +* failure. The best we can do is to handle +* vblank now, so there is no vblank/flip_done +* time outs +*/ +drm_crtc_handle_vblank (&pipeline->pipe.crtc); + } + } +} + +static int display_prepare_fb (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *plane_state) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe); + +if (pipeline->pgflip_last_error) { +int ret; + +/* if previous page flip didn't succeed then report the error */ Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c line 207
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +5
-0+ ret = pipeline->pgflip_last_error; +/* and let us try to page flip next time */ + pipeline->pgflip_last_error =0 ; +return ret; + }Nope, this isn't how the uapi works. If your flips fail then we might need to add some error status thing to the drm events, but you can't make the next flip fail.
Well, yes, there is no way for me to tell that the page flip has failed, so this is why I tried to do this workaround with the next page-flip. The reason for that is that if, for example, we are disconnected from the backend for some reason, there is no way for me to tell the user-space that hey, please, do not send any other page flips. If backend can recover and that was a one time error then yes, the code I have will do wrong thing (fail the current page flip), but if the error state is persistent then I will be able to tell the user-space to stop by returning errors. This is kind of trade-off which I am not sure how to solve correctly.
Quoted 1 line
Do you think I can remove this workaround completely?
Yes. If you want to tell userspace that the backend is gone, send a hotplug uevent and update the connector status to disconnected. Hotplug uevents is how we tell userspace about asynchronous changes. We also have special stuff to signal display cable issue that might require picking a lower resolution (DP link training) and when HDCP encryption failed.
Sending back random errors on pageflips just confuses the compositor, and all correctly working compositors will listen to hotplug events and reprobe all the outputs and change the configuration if necessary. -Daniel
Quoted 142 lines
Quoted 133 lines
-Daniel
Quoted 131 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +92
-0+return drm_gem_fb_prepare_fb (&pipe->plane, plane_state); +} + +static void display_update (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *old_plane_state) +{ +struct drm_crtc *crtc = &pipe->crtc; +struct drm_pending_vblank_event *event; + + event = crtc->state->event; +if (event) { +struct drm_device *dev = crtc->dev; +unsigned long flags; + + crtc->state->event =NULL ; + +spin_lock_irqsave (&dev->event_lock, flags); +if (drm_crtc_vblank_get (crtc) ==0 ) +drm_crtc_arm_vblank_event (crtc, event); +else +drm_crtc_send_vblank_event (crtc, event); +spin_unlock_irqrestore (&dev->event_lock, flags); + } +/* +* Send page flip request to the backend *after* we have event armed/ +* sent above, so on page flip done event from the backend we can +* deliver it while handling vblank. +*/ +display_send_page_flip (pipe, old_plane_state); +} + +static const struct drm_simple_display_pipe_funcs display_funcs = { + .enable = display_enable, + .disable = display_disable, + .prepare_fb = display_prepare_fb, + .update = display_update, +}; + +static int display_pipe_init (struct xen_drm_front_drm_info *drm_info, +int index,struct xen_drm_front_cfg_connector *cfg, +struct xen_drm_front_drm_pipeline *pipeline) +{ +struct drm_device *dev = drm_info->drm_dev; +const uint32_t *formats; +int format_count; +int ret; + + pipeline->drm_info = drm_info; + pipeline->index = index; + pipeline->height = cfg->height; + pipeline->width = cfg->width; + + ret =xen_drm_front_conn_init (drm_info, &pipeline->conn); +if (ret) +return ret; + + formats =xen_drm_front_conn_get_formats (&format_count); + +return drm_simple_display_pipe_init (dev, &pipeline->pipe, + &display_funcs, formats, format_count, +NULL , &pipeline->conn); +} + +int xen_drm_front_kms_init (struct xen_drm_front_drm_info *drm_info) +{ +struct drm_device *dev = drm_info->drm_dev; +int i, ret; + +drm_mode_config_init (dev); + + dev->mode_config.min_width =0 ; + dev->mode_config.min_height =0 ; + dev->mode_config.max_width =4095 ; + dev->mode_config.max_height =2047 ; + dev->mode_config.funcs = &mode_config_funcs; + +for (i =0 ; i < drm_info->cfg->num_connectors; i++) { +struct xen_drm_front_cfg_connector *cfg = + &drm_info->cfg->connectors[i]; +struct xen_drm_front_drm_pipeline *pipeline = + &drm_info->pipeline[i]; + + ret =display_pipe_init (drm_info, i, cfg, pipeline); +if (ret) { +drm_mode_config_cleanup (dev); +return ret; + } + } + +drm_mode_config_reset (dev); +return 0 ; +}drivers/gpu/drm/xen/xen_drm_front_kms.h new file +30
-0@@ -0,0 +1,30 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_KMS_H_ +#define __XEN_DRM_FRONT_KMS_H_ + +#include "xen_drm_front_drv.h" + +int xen_drm_front_kms_init (struct xen_drm_front_drm_info *drm_info); + +void xen_drm_front_kms_on_frame_done ( +struct xen_drm_front_drm_pipeline *pipeline, +uint64_t fb_cookie); + +#endif /* __XEN_DRM_FRONT_KMS_H_ */ Signature · 1 line
2.7.4Quoted 4 lines
Quoted 4 lines
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel[1] https://patchwork.kernel.org/patch/10211997/
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Signature · 8 lines
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ Xen-devel mailing list [email protected] https://lists.xenproject.org/mailman/listinfo/xen-devel
Re: [PATCH 7/9] drm/xen-front: Implement KMS/connector handling
In reply to Daniel VetterQuoted 26 lines · Daniel Vetter
Quoted 25 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Implement kernel modesetiing/connector handling using DRM simple KMS helper pipeline:
- implement KMS part of the driver with the help of DRM simple pipepline helper which is possible due to the fact that the para-virtualized driver only supports a single (primary) plane:
- initialize connectors according to XenStore configuration
- handle frame done events from the backend
- generate vblank events
- create and destroy frame buffers and propagate those to the backend
- propagate set/reset mode configuration to the backend on display enable/disable callbacks
- send page flip request to the backend and implement logic for reporting backend IO errors on prepare fb callback- implement virtual connector handling:
- support only pixel formats suitable for single plane modes
- make sure the connector is always connected
- support a single video mode as per para-virtualized driver configuration
Quoted 3 lines
Quoted 1 line
Signed-off-by Oleksandr Andrushchenko <[email protected]>I think once you've removed the midlayer in the previous patch it would makes sense to merge the 2 patches into 1.
ok, will squash the two
Quoted 400 lines
Bunch more comments below.
-DanielQuoted 396 lines
--- drivers/gpu/drm/xen/Makefile | 2 + drivers/gpu/drm/xen/xen_drm_front_conn.c | 125 +++++++++++++ drivers/gpu/drm/xen/xen_drm_front_conn.h | 35 ++++ drivers/gpu/drm/xen/xen_drm_front_drv.c | 15 ++ drivers/gpu/drm/xen/xen_drm_front_drv.h | 12 ++ drivers/gpu/drm/xen/xen_drm_front_kms.c | 299 +++++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_kms.h | 30 ++++ 7 files changed, 518 insertions(+)create mode 100644
drivers/gpu/drm/xen/xen_drm_front_conn.ccreate mode 100644drivers/gpu/drm/xen/xen_drm_front_conn.hcreate mode 100644drivers/gpu/drm/xen/xen_drm_front_kms.ccreate mode 100644drivers/gpu/drm/xen/xen_drm_front_kms.hdrivers/gpu/drm/xen/Makefile +2
-0@@ -2,6 +2,8 @@ drm_xen_front-objs := xen_drm_front.o \ xen_drm_front_drv.o \ + xen_drm_front_kms.o \ + xen_drm_front_conn.o \ xen_drm_front_evtchnl.o \ xen_drm_front_shbuf.o \ xen_drm_front_cfg.odrivers/gpu/drm/xen/xen_drm_front_conn.c new file +125
-0@@ -0,0 +1,125 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_crtc_helper.h> + +#include <video/videomode.h> + +#include "xen_drm_front_conn.h" +#include "xen_drm_front_drv.h" + +static struct xen_drm_front_drm_pipeline * +to_xen_drm_pipeline (struct drm_connector *connector) +{ + return container_of(connector, struct xen_drm_front_drm_pipeline, conn); +} + +static const uint32_t plane_formats[] = { +DRM_FORMAT_RGB565 , +DRM_FORMAT_RGB888 , +DRM_FORMAT_XRGB8888 , +DRM_FORMAT_ARGB8888 , +DRM_FORMAT_XRGB4444 , +DRM_FORMAT_ARGB4444 , +DRM_FORMAT_XRGB1555 , +DRM_FORMAT_ARGB1555 , +}; + +const uint32_t *xen_drm_front_conn_get_formats (int *format_count) +{ + *format_count =ARRAY_SIZE (plane_formats); +return plane_formats; +} + +static enum drm_connector_status connector_detect ( +struct drm_connector *connector,bool force) +{ +if (drm_dev_is_unplugged (connector->dev)) +return connector_status_disconnected; + +return connector_status_connected; +} + +#define XEN_DRM_NUM_VIDEO_MODES 1 +#define XEN_DRM_CRTC_VREFRESH_HZ 60 + +static int connector_get_modes (struct drm_connector *connector) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (connector); +struct drm_display_mode *mode; +struct videomode videomode; +int width, height; + + mode =drm_mode_create (connector->dev); +if (!mode) +return 0 ; + +memset (&videomode,0 ,sizeof (videomode)); + videomode.hactive = pipeline->width; + videomode.vactive = pipeline->height; + width = videomode.hactive + videomode.hfront_porch + + videomode.hback_porch + videomode.hsync_len; + height = videomode.vactive + videomode.vfront_porch + + videomode.vback_porch + videomode.vsync_len; + videomode.pixelclock = width * height *XEN_DRM_CRTC_VREFRESH_HZ ; + mode->type =DRM_MODE_TYPE_PREFERRED |DRM_MODE_TYPE_DRIVER ; + +drm_display_mode_from_videomode (&videomode, mode); +drm_mode_probed_add (connector, mode); +return XEN_DRM_NUM_VIDEO_MODES ; +} + +static int connector_mode_valid (struct drm_connector *connector, +struct drm_display_mode *mode) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (connector); + +if (mode->hdisplay != pipeline->width) +return MODE_ERROR ; + +if (mode->vdisplay != pipeline->height) +return MODE_ERROR ; + +return MODE_OK ; +} + +static const struct drm_connector_helper_funcs connector_helper_funcs = { + .get_modes = connector_get_modes, + .mode_valid = connector_mode_valid, +}; + +static const struct drm_connector_funcs connector_funcs = { + .detect = connector_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +int xen_drm_front_conn_init (struct xen_drm_front_drm_info *drm_info, +struct drm_connector *connector) +{ +drm_connector_helper_add (connector, &connector_helper_funcs); + +return drm_connector_init (drm_info->drm_dev, connector, + &connector_funcs,DRM_MODE_CONNECTOR_VIRTUAL ); +}drivers/gpu/drm/xen/xen_drm_front_conn.h new file +35
-0@@ -0,0 +1,35 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_CONN_H_ +#define __XEN_DRM_FRONT_CONN_H_ + +#include <drm/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_encoder.h> + +#include <linux/wait.h> + +struct xen_drm_front_drm_info ; + +const uint32_t *xen_drm_front_conn_get_formats (int *format_count); + +int xen_drm_front_conn_init (struct xen_drm_front_drm_info *drm_info, +struct drm_connector *connector); + +#endif /* __XEN_DRM_FRONT_CONN_H_ */ drivers/gpu/drm/xen/xen_drm_front_drv.c +15
-0@@ -23,6 +23,7 @@#include "xen_drm_front.h" #include "xen_drm_front_cfg.h" #include "xen_drm_front_drv.h" +#include "xen_drm_front_kms.h" static int dumb_create (struct drm_file *filp,struct drm_device *dev,struct drm_mode_create_dumb *args)@@ -41,6 +42,13 @@ static void free_object(struct drm_gem_object *obj)static void on_frame_done (struct platform_device *pdev,int conn_idx,uint64_t fb_cookie) { +struct xen_drm_front_drm_info *drm_info =platform_get_drvdata (pdev); + +if (unlikely (conn_idx >= drm_info->cfg->num_connectors)) +return ; + +xen_drm_front_kms_on_frame_done (&drm_info->pipeline[conn_idx], + fb_cookie); }static void lastclose (struct drm_device *dev)@@ -157,6 +165,12 @@ int xen_drm_front_drv_probe(struct platform_device *pdev,return ret; } + ret =xen_drm_front_kms_init (drm_info); +if (ret) { +DRM_ERROR ("Failed to initialize DRM/KMS, ret %d\n" , ret); + goto fail_modeset; + } + dev->irq_enabled =1 ; ret =drm_dev_register (dev,0 );@@ -172,6 +186,7 @@ int xen_drm_front_drv_probe(struct platform_device *pdev, fail_register:drm_dev_unregister (dev); +fail_modeset:drm_mode_config_cleanup (dev);return ret; }drivers/gpu/drm/xen/xen_drm_front_drv.h +12
-0@@ -20,14 +20,24 @@#define __XEN_DRM_FRONT_DRV_H_#include <drm/drmP.h> +#include <drm/drm_simple_kms_helper.h> #include "xen_drm_front.h" #include "xen_drm_front_cfg.h" +#include "xen_drm_front_conn.h" struct xen_drm_front_drm_pipeline {struct xen_drm_front_drm_info *drm_info;int index; + +struct drm_simple_display_pipe pipe; + +struct drm_connector conn; +/* these are only for connector mode checking */ +int width, height; +/* last backend error seen on page flip */ +int pgflip_last_error; };struct xen_drm_front_drm_info {@@ -35,6 +45,8 @@ struct xen_drm_front_drm_info {struct xen_drm_front_ops *front_ops;struct drm_device *drm_dev;struct xen_drm_front_cfg *cfg; + +struct xen_drm_front_drm_pipeline pipeline[XEN_DRM_FRONT_MAX_CRTCS ]; }; static inline uint64_t xen_drm_front_fb_to_cookie(drivers/gpu/drm/xen/xen_drm_front_kms.c new file +106
-0@@ -0,0 +1,299 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include "xen_drm_front_kms.h" + +#include <drm/drmP.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_gem.h> +#include <drm/drm_gem_framebuffer_helper.h> + +#include "xen_drm_front.h" +#include "xen_drm_front_conn.h" +#include "xen_drm_front_drv.h" + +static struct xen_drm_front_drm_pipeline * +to_xen_drm_pipeline (struct drm_simple_display_pipe *pipe) +{ + return container_of(pipe, struct xen_drm_front_drm_pipeline, pipe); +} + +static void fb_destroy (struct drm_framebuffer *fb) +{ +struct xen_drm_front_drm_info *drm_info = fb->dev->dev_private; + + drm_info->front_ops->fb_detach (drm_info->front_info, +xen_drm_front_fb_to_cookie (fb)); +drm_gem_fb_destroy (fb); +} + +static struct drm_framebuffer_funcs fb_funcs = { + .destroy = fb_destroy, +}; + +static struct drm_framebuffer *fb_create (struct drm_device *dev, +struct drm_file *filp,const struct drm_mode_fb_cmd2 *mode_cmd) +{ +struct xen_drm_front_drm_info *drm_info = dev->dev_private; +static struct drm_framebuffer *fb; +struct drm_gem_object *gem_obj; +int ret; + + fb =drm_gem_fb_create_with_funcs (dev, filp, mode_cmd, &fb_funcs); +if (IS_ERR_OR_NULL (fb)) +return fb; + + gem_obj =drm_gem_object_lookup (filp, mode_cmd->handles[0 ]); +if (!gem_obj) { +DRM_ERROR ("Failed to lookup GEM object\n" ); + ret = -ENOENT ; + goto fail; + } + +drm_gem_object_unreference_unlocked (gem_obj); + + ret = drm_info->front_ops->fb_attach ( + drm_info->front_info, +xen_drm_front_dbuf_to_cookie (gem_obj), +xen_drm_front_fb_to_cookie (fb), + fb->width, fb->height, fb->format->format); +if (ret <0 ) { +DRM_ERROR ("Back failed to attach FB %p: %d\n" , fb, ret); + goto fail; + } + +return fb; + +fail: +drm_gem_fb_destroy (fb); +return ERR_PTR (ret); +} + +static const struct drm_mode_config_funcs mode_config_funcs = { + .fb_create = fb_create, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +static int display_set_config (struct drm_simple_display_pipe *pipe, +struct drm_framebuffer *fb) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe); +struct drm_crtc *crtc = &pipe->crtc; +struct xen_drm_front_drm_info *drm_info = pipeline->drm_info; +int ret; + +if (fb) + ret = drm_info->front_ops->mode_set(pipeline, + crtc->x, crtc->y, + fb->width, fb->height, fb->format->cpp[0] * 8,
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c line 111
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +5
-0+ xen_drm_front_fb_to_cookie(fb)); + else + ret = drm_info->front_ops->mode_set (pipeline, +0 ,0 ,0 ,0 ,0 , +xen_drm_front_fb_to_cookie (NULL ));This is a bit much layering, the if (fb) case corresponds to the display_enable/disable hooks, pls fold that in instead of the indirection. simple helpers guarantee that when the display is on, then you have an fb.
1. Ok, the only reason for having this function was to keep front_ops->mode_set calls at one place (will be refactored to be a direct call, not via front_ops).
2. The if (fb) check was meant not to check if simple helpers may give us some wrong value when we do not expect: there is nothing wrong with them. The check was for 2 cases when this function was called: with fb != NULL on display enable and with fb == NULL on display disable, e.g. fb was used as a flag in this check.
3. I will remove this function at all and will make direct calls to the backend on .display_{enable|disable}
Quoted 3 lines
Maybe we need to fix the docs, pls check and if that's not clear, submit a kernel-doc patch for the simple pipe helpers.
no, nothing wrong here, just see my reasoning above
Quoted 9 lines
Quoted 9 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +9
-0+ +if (ret) +DRM_ERROR ("Failed to set mode to back: %d\n" , ret); + +return ret; +} + +static void display_enable (struct drm_simple_display_pipe *pipe, +struct drm_crtc_state *crtc_state)
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c line 126
Quoted 6 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +6
-0+{ +struct drm_crtc *crtc = &pipe->crtc; +struct drm_framebuffer *fb = pipe->plane.state->fb; + +if (display_set_config (pipe, fb) ==0 ) +drm_crtc_vblank_on (crtc);I get the impression your driver doesn't support vblanks (the page flip code at least looks like it's only generating a single event),
yes, this is true
Quoted 2 lines
you also
don't have a enable/disable_vblank implementation.
this is because with my previous patches [1] these are now handled by simple helpers, so no need to provide dummy ones in the driver
Quoted 2 lines
If there's no vblank
handling then this shouldn't be needed.
yes, I will rework the code, please see below
Quoted 21 lines
Quoted 21 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +21
-0+else +DRM_ERROR ("Failed to enable display\n" ); +} + +static void display_disable (struct drm_simple_display_pipe *pipe) +{ +struct drm_crtc *crtc = &pipe->crtc; + +display_set_config (pipe,NULL ); +drm_crtc_vblank_off (crtc); +/* final check for stalled events */ +if (crtc->state->event && !crtc->state->active) { +unsigned long flags; + +spin_lock_irqsave (&crtc->dev->event_lock, flags); +drm_crtc_send_vblank_event (crtc, crtc->state->event); +spin_unlock_irqrestore (&crtc->dev->event_lock, flags); + crtc->state->event =NULL ; + } +} +
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c line 152
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +5
-0+void xen_drm_front_kms_on_frame_done ( +struct xen_drm_front_drm_pipeline *pipeline, +uint64_t fb_cookie) +{ +drm_crtc_handle_vblank (&pipeline->pipe.crtc);Hm, again this doesn't look like real vblank, but only a page-flip done event. If that's correct then please don't use the vblank machinery, but just store the event internally (protected with your own private spinlock)
Why can't I use &dev->event_lock? Anyways for handling page-flip events I will need to lock on it, so I can do drm_crtc_send_vblank_event?
Quoted 3 lines
and send it out using
drm_crtc_send_vblank_eventdirectly. No calls toarm_vblank_eventor any of the other vblank infrastructure should be needed.
will re-work, e.g. will store drm_pending_vblank_event on .display_update and send out on page flip event from the backend
Quoted 3 lines
Also please remove the
drm_vblank_init()call, since your hw doesn't really have vblanks. And exposing vblanks to userspace without implementing them is confusing.
will remove all vblank handling at all with the re-work above
Quoted 51 lines
Quoted 51 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +50
-0+} + +static void display_send_page_flip (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *old_plane_state) +{ +struct drm_plane_state *plane_state =drm_atomic_get_new_plane_state ( + old_plane_state->state, &pipe->plane); + +/* +* If old_plane_state->fb is NULL and plane_state->fb is not, +* then this is an atomic commit which will enable display. +* If old_plane_state->fb is not NULL and plane_state->fb is, +* then this is an atomic commit which will disable display. +* Ignore these and do not send page flip as this framebuffer will be +* sent to the backend as a part of display_set_config call. +*/ +if (old_plane_state->fb && plane_state->fb) { +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe); +struct xen_drm_front_drm_info *drm_info = pipeline->drm_info; +int ret; + + ret = drm_info->front_ops->page_flip (drm_info->front_info, + pipeline->index, +xen_drm_front_fb_to_cookie (plane_state->fb)); + pipeline->pgflip_last_error = ret; +if (ret) { +DRM_ERROR ("Failed to send page flip request to backend: %d\n" , ret); +/* +* As we are at commit stage the DRM core will anyways +* wait for the vblank and knows nothing about our +* failure. The best we can do is to handle +* vblank now, so there is no vblank/flip_done +* time outs +*/ +drm_crtc_handle_vblank (&pipeline->pipe.crtc); + } + } +} + +static int display_prepare_fb (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *plane_state) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe); + +if (pipeline->pgflip_last_error) { +int ret; + +/* if previous page flip didn't succeed then report the error */
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c line 207
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +5
-0+ ret = pipeline->pgflip_last_error; +/* and let us try to page flip next time */ + pipeline->pgflip_last_error =0 ; +return ret; + }Nope, this isn't how the uapi works. If your flips fail then we might need to add some error status thing to the drm events, but you can't make the next flip fail.
Well, yes, there is no way for me to tell that the page flip has failed, so this is why I tried to do this workaround with the next page-flip. The reason for that is that if, for example, we are disconnected from the backend for some reason, there is no way for me to tell the user-space that hey, please, do not send any other page flips. If backend can recover and that was a one time error then yes, the code I have will do wrong thing (fail the current page flip), but if the error state is persistent then I will be able to tell the user-space to stop by returning errors. This is kind of trade-off which I am not sure how to solve correctly.
Do you think I can remove this workaround completely?
Quoted 133 lines
-Daniel
Quoted 131 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +92
-0+return drm_gem_fb_prepare_fb (&pipe->plane, plane_state); +} + +static void display_update (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *old_plane_state) +{ +struct drm_crtc *crtc = &pipe->crtc; +struct drm_pending_vblank_event *event; + + event = crtc->state->event; +if (event) { +struct drm_device *dev = crtc->dev; +unsigned long flags; + + crtc->state->event =NULL ; + +spin_lock_irqsave (&dev->event_lock, flags); +if (drm_crtc_vblank_get (crtc) ==0 ) +drm_crtc_arm_vblank_event (crtc, event); +else +drm_crtc_send_vblank_event (crtc, event); +spin_unlock_irqrestore (&dev->event_lock, flags); + } +/* +* Send page flip request to the backend *after* we have event armed/ +* sent above, so on page flip done event from the backend we can +* deliver it while handling vblank. +*/ +display_send_page_flip (pipe, old_plane_state); +} + +static const struct drm_simple_display_pipe_funcs display_funcs = { + .enable = display_enable, + .disable = display_disable, + .prepare_fb = display_prepare_fb, + .update = display_update, +}; + +static int display_pipe_init (struct xen_drm_front_drm_info *drm_info, +int index,struct xen_drm_front_cfg_connector *cfg, +struct xen_drm_front_drm_pipeline *pipeline) +{ +struct drm_device *dev = drm_info->drm_dev; +const uint32_t *formats; +int format_count; +int ret; + + pipeline->drm_info = drm_info; + pipeline->index = index; + pipeline->height = cfg->height; + pipeline->width = cfg->width; + + ret =xen_drm_front_conn_init (drm_info, &pipeline->conn); +if (ret) +return ret; + + formats =xen_drm_front_conn_get_formats (&format_count); + +return drm_simple_display_pipe_init (dev, &pipeline->pipe, + &display_funcs, formats, format_count, +NULL , &pipeline->conn); +} + +int xen_drm_front_kms_init (struct xen_drm_front_drm_info *drm_info) +{ +struct drm_device *dev = drm_info->drm_dev; +int i, ret; + +drm_mode_config_init (dev); + + dev->mode_config.min_width =0 ; + dev->mode_config.min_height =0 ; + dev->mode_config.max_width =4095 ; + dev->mode_config.max_height =2047 ; + dev->mode_config.funcs = &mode_config_funcs; + +for (i =0 ; i < drm_info->cfg->num_connectors; i++) { +struct xen_drm_front_cfg_connector *cfg = + &drm_info->cfg->connectors[i]; +struct xen_drm_front_drm_pipeline *pipeline = + &drm_info->pipeline[i]; + + ret =display_pipe_init (drm_info, i, cfg, pipeline); +if (ret) { +drm_mode_config_cleanup (dev); +return ret; + } + } + +drm_mode_config_reset (dev); +return 0 ; +}drivers/gpu/drm/xen/xen_drm_front_kms.h new file +30
-0@@ -0,0 +1,30 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_KMS_H_ +#define __XEN_DRM_FRONT_KMS_H_ + +#include "xen_drm_front_drv.h" + +int xen_drm_front_kms_init (struct xen_drm_front_drm_info *drm_info); + +void xen_drm_front_kms_on_frame_done ( +struct xen_drm_front_drm_pipeline *pipeline, +uint64_t fb_cookie); + +#endif /* __XEN_DRM_FRONT_KMS_H_ */ Signature · 1 line
2.7.4
Quoted 4 lines
Quoted 4 lines
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
[1] https://patchwork.kernel.org/patch/10211997/
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Re: [PATCH 7/9] drm/xen-front: Implement KMS/connector handling
In reply to Oleksandr AndrushchenkoQuoted 19 lines · Oleksandr Andrushchenko
From: Oleksandr Andrushchenko <[email protected]>
Implement kernel modesetiing/connector handling using DRM simple KMS helper pipeline:
- implement KMS part of the driver with the help of DRM simple pipepline helper which is possible due to the fact that the para-virtualized driver only supports a single (primary) plane:
- initialize connectors according to XenStore configuration
- handle frame done events from the backend
- generate vblank events
- create and destroy frame buffers and propagate those to the backend
- propagate set/reset mode configuration to the backend on display enable/disable callbacks
- send page flip request to the backend and implement logic for reporting backend IO errors on prepare fb callback
Quoted 7 lines
- implement virtual connector handling:
- support only pixel formats suitable for single plane modes
- make sure the connector is always connected
- support a single video mode as per para-virtualized driver configurationSigned-off-by Oleksandr Andrushchenko <[email protected]>
I think once you've removed the midlayer in the previous patch it would makes sense to merge the 2 patches into 1.
Bunch more comments below.
-Daniel
Quoted 391 lines
--- drivers/gpu/drm/xen/Makefile | 2 + drivers/gpu/drm/xen/xen_drm_front_conn.c | 125 +++++++++++++ drivers/gpu/drm/xen/xen_drm_front_conn.h | 35 ++++ drivers/gpu/drm/xen/xen_drm_front_drv.c | 15 ++ drivers/gpu/drm/xen/xen_drm_front_drv.h | 12 ++ drivers/gpu/drm/xen/xen_drm_front_kms.c | 299 +++++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_kms.h | 30 ++++ 7 files changed, 518 insertions(+) create mode 100644 drivers/gpu/drm/xen/xen_drm_front_conn.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_conn.h create mode 100644 drivers/gpu/drm/xen/xen_drm_front_kms.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_kms.hdrivers/gpu/drm/xen/Makefile +2
-0@@ -2,6 +2,8 @@ drm_xen_front-objs := xen_drm_front.o \ xen_drm_front_drv.o \ + xen_drm_front_kms.o \ + xen_drm_front_conn.o \ xen_drm_front_evtchnl.o \ xen_drm_front_shbuf.o \ xen_drm_front_cfg.odrivers/gpu/drm/xen/xen_drm_front_conn.c new file +125
-0@@ -0,0 +1,125 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_crtc_helper.h> + +#include <video/videomode.h> + +#include "xen_drm_front_conn.h" +#include "xen_drm_front_drv.h" + +static struct xen_drm_front_drm_pipeline * +to_xen_drm_pipeline (struct drm_connector *connector) +{ + return container_of(connector, struct xen_drm_front_drm_pipeline, conn); +} + +static const uint32_t plane_formats[] = { +DRM_FORMAT_RGB565 , +DRM_FORMAT_RGB888 , +DRM_FORMAT_XRGB8888 , +DRM_FORMAT_ARGB8888 , +DRM_FORMAT_XRGB4444 , +DRM_FORMAT_ARGB4444 , +DRM_FORMAT_XRGB1555 , +DRM_FORMAT_ARGB1555 , +}; + +const uint32_t *xen_drm_front_conn_get_formats (int *format_count) +{ + *format_count =ARRAY_SIZE (plane_formats); +return plane_formats; +} + +static enum drm_connector_status connector_detect ( +struct drm_connector *connector,bool force) +{ +if (drm_dev_is_unplugged (connector->dev)) +return connector_status_disconnected; + +return connector_status_connected; +} + +#define XEN_DRM_NUM_VIDEO_MODES 1 +#define XEN_DRM_CRTC_VREFRESH_HZ 60 + +static int connector_get_modes (struct drm_connector *connector) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (connector); +struct drm_display_mode *mode; +struct videomode videomode; +int width, height; + + mode =drm_mode_create (connector->dev); +if (!mode) +return 0 ; + +memset (&videomode,0 ,sizeof (videomode)); + videomode.hactive = pipeline->width; + videomode.vactive = pipeline->height; + width = videomode.hactive + videomode.hfront_porch + + videomode.hback_porch + videomode.hsync_len; + height = videomode.vactive + videomode.vfront_porch + + videomode.vback_porch + videomode.vsync_len; + videomode.pixelclock = width * height *XEN_DRM_CRTC_VREFRESH_HZ ; + mode->type =DRM_MODE_TYPE_PREFERRED |DRM_MODE_TYPE_DRIVER ; + +drm_display_mode_from_videomode (&videomode, mode); +drm_mode_probed_add (connector, mode); +return XEN_DRM_NUM_VIDEO_MODES ; +} + +static int connector_mode_valid (struct drm_connector *connector, +struct drm_display_mode *mode) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (connector); + +if (mode->hdisplay != pipeline->width) +return MODE_ERROR ; + +if (mode->vdisplay != pipeline->height) +return MODE_ERROR ; + +return MODE_OK ; +} + +static const struct drm_connector_helper_funcs connector_helper_funcs = { + .get_modes = connector_get_modes, + .mode_valid = connector_mode_valid, +}; + +static const struct drm_connector_funcs connector_funcs = { + .detect = connector_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +int xen_drm_front_conn_init (struct xen_drm_front_drm_info *drm_info, +struct drm_connector *connector) +{ +drm_connector_helper_add (connector, &connector_helper_funcs); + +return drm_connector_init (drm_info->drm_dev, connector, + &connector_funcs,DRM_MODE_CONNECTOR_VIRTUAL ); +}drivers/gpu/drm/xen/xen_drm_front_conn.h new file +35
-0@@ -0,0 +1,35 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_CONN_H_ +#define __XEN_DRM_FRONT_CONN_H_ + +#include <drm/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_encoder.h> + +#include <linux/wait.h> + +struct xen_drm_front_drm_info ; + +const uint32_t *xen_drm_front_conn_get_formats (int *format_count); + +int xen_drm_front_conn_init (struct xen_drm_front_drm_info *drm_info, +struct drm_connector *connector); + +#endif /* __XEN_DRM_FRONT_CONN_H_ */ drivers/gpu/drm/xen/xen_drm_front_drv.c +15
-0@@ -23,6 +23,7 @@#include "xen_drm_front.h" #include "xen_drm_front_cfg.h" #include "xen_drm_front_drv.h" +#include "xen_drm_front_kms.h" static int dumb_create (struct drm_file *filp,struct drm_device *dev,struct drm_mode_create_dumb *args)@@ -41,6 +42,13 @@ static void free_object(struct drm_gem_object *obj)static void on_frame_done (struct platform_device *pdev,int conn_idx,uint64_t fb_cookie) { +struct xen_drm_front_drm_info *drm_info =platform_get_drvdata (pdev); + +if (unlikely (conn_idx >= drm_info->cfg->num_connectors)) +return ; + +xen_drm_front_kms_on_frame_done (&drm_info->pipeline[conn_idx], + fb_cookie); }static void lastclose (struct drm_device *dev)@@ -157,6 +165,12 @@ int xen_drm_front_drv_probe(struct platform_device *pdev,return ret; } + ret =xen_drm_front_kms_init (drm_info); +if (ret) { +DRM_ERROR ("Failed to initialize DRM/KMS, ret %d\n" , ret); + goto fail_modeset; + } + dev->irq_enabled =1 ; ret =drm_dev_register (dev,0 );@@ -172,6 +186,7 @@ int xen_drm_front_drv_probe(struct platform_device *pdev, fail_register:drm_dev_unregister (dev); +fail_modeset:drm_mode_config_cleanup (dev);return ret; }drivers/gpu/drm/xen/xen_drm_front_drv.h +12
-0@@ -20,14 +20,24 @@#define __XEN_DRM_FRONT_DRV_H_#include <drm/drmP.h> +#include <drm/drm_simple_kms_helper.h> #include "xen_drm_front.h" #include "xen_drm_front_cfg.h" +#include "xen_drm_front_conn.h" struct xen_drm_front_drm_pipeline {struct xen_drm_front_drm_info *drm_info;int index; + +struct drm_simple_display_pipe pipe; + +struct drm_connector conn; +/* these are only for connector mode checking */ +int width, height; +/* last backend error seen on page flip */ +int pgflip_last_error; };struct xen_drm_front_drm_info {@@ -35,6 +45,8 @@ struct xen_drm_front_drm_info {struct xen_drm_front_ops *front_ops;struct drm_device *drm_dev;struct xen_drm_front_cfg *cfg; + +struct xen_drm_front_drm_pipeline pipeline[XEN_DRM_FRONT_MAX_CRTCS ]; }; static inline uint64_t xen_drm_front_fb_to_cookie(drivers/gpu/drm/xen/xen_drm_front_kms.c new file +101
-0@@ -0,0 +1,299 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#include "xen_drm_front_kms.h" + +#include <drm/drmP.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_gem.h> +#include <drm/drm_gem_framebuffer_helper.h> + +#include "xen_drm_front.h" +#include "xen_drm_front_conn.h" +#include "xen_drm_front_drv.h" + +static struct xen_drm_front_drm_pipeline * +to_xen_drm_pipeline (struct drm_simple_display_pipe *pipe) +{ + return container_of(pipe, struct xen_drm_front_drm_pipeline, pipe); +} + +static void fb_destroy (struct drm_framebuffer *fb) +{ +struct xen_drm_front_drm_info *drm_info = fb->dev->dev_private; + + drm_info->front_ops->fb_detach (drm_info->front_info, +xen_drm_front_fb_to_cookie (fb)); +drm_gem_fb_destroy (fb); +} + +static struct drm_framebuffer_funcs fb_funcs = { + .destroy = fb_destroy, +}; + +static struct drm_framebuffer *fb_create (struct drm_device *dev, +struct drm_file *filp,const struct drm_mode_fb_cmd2 *mode_cmd) +{ +struct xen_drm_front_drm_info *drm_info = dev->dev_private; +static struct drm_framebuffer *fb; +struct drm_gem_object *gem_obj; +int ret; + + fb =drm_gem_fb_create_with_funcs (dev, filp, mode_cmd, &fb_funcs); +if (IS_ERR_OR_NULL (fb)) +return fb; + + gem_obj =drm_gem_object_lookup (filp, mode_cmd->handles[0 ]); +if (!gem_obj) { +DRM_ERROR ("Failed to lookup GEM object\n" ); + ret = -ENOENT ; + goto fail; + } + +drm_gem_object_unreference_unlocked (gem_obj); + + ret = drm_info->front_ops->fb_attach ( + drm_info->front_info, +xen_drm_front_dbuf_to_cookie (gem_obj), +xen_drm_front_fb_to_cookie (fb), + fb->width, fb->height, fb->format->format); +if (ret <0 ) { +DRM_ERROR ("Back failed to attach FB %p: %d\n" , fb, ret); + goto fail; + } + +return fb; + +fail: +drm_gem_fb_destroy (fb); +return ERR_PTR (ret); +} + +static const struct drm_mode_config_funcs mode_config_funcs = { + .fb_create = fb_create, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +static int display_set_config (struct drm_simple_display_pipe *pipe, +struct drm_framebuffer *fb) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe); +struct drm_crtc *crtc = &pipe->crtc; +struct xen_drm_front_drm_info *drm_info = pipeline->drm_info; +int ret;
drivers/gpu/drm/xen/xen_drm_front_kms.c line 111
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +10
-0+ +if (fb) + ret = drm_info->front_ops->mode_set (pipeline, + crtc->x, crtc->y, + fb->width, fb->height, fb->format->cpp[0 ] *8 , +xen_drm_front_fb_to_cookie (fb)); +else + ret = drm_info->front_ops->mode_set (pipeline, +0 ,0 ,0 ,0 ,0 , +xen_drm_front_fb_to_cookie (NULL ));
This is a bit much layering, the if (fb) case corresponds to the display_enable/disable hooks, pls fold that in instead of the indirection. simple helpers guarantee that when the display is on, then you have an fb.
Maybe we need to fix the docs, pls check and if that's not clear, submit a kernel-doc patch for the simple pipe helpers.
Quoted 5 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +5
-0+ +if (ret) +DRM_ERROR ("Failed to set mode to back: %d\n" , ret); + +return ret;
drivers/gpu/drm/xen/xen_drm_front_kms.c line 126
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +10
-0+} + +static void display_enable (struct drm_simple_display_pipe *pipe, +struct drm_crtc_state *crtc_state) +{ +struct drm_crtc *crtc = &pipe->crtc; +struct drm_framebuffer *fb = pipe->plane.state->fb; + +if (display_set_config (pipe, fb) ==0 ) +drm_crtc_vblank_on (crtc);
I get the impression your driver doesn't support vblanks (the page flip code at least looks like it's only generating a single event), you also don't have a enable/disable_vblank implementation. If there's no vblank handling then this shouldn't be needed.
Quoted 16 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +16
-0+else +DRM_ERROR ("Failed to enable display\n" ); +} + +static void display_disable (struct drm_simple_display_pipe *pipe) +{ +struct drm_crtc *crtc = &pipe->crtc; + +display_set_config (pipe,NULL ); +drm_crtc_vblank_off (crtc); +/* final check for stalled events */ +if (crtc->state->event && !crtc->state->active) { +unsigned long flags; + +spin_lock_irqsave (&crtc->dev->event_lock, flags); +drm_crtc_send_vblank_event (crtc, crtc->state->event);
drivers/gpu/drm/xen/xen_drm_front_kms.c line 152
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +10
-0+spin_unlock_irqrestore (&crtc->dev->event_lock, flags); + crtc->state->event =NULL ; + } +} + +void xen_drm_front_kms_on_frame_done ( +struct xen_drm_front_drm_pipeline *pipeline, +uint64_t fb_cookie) +{ +drm_crtc_handle_vblank (&pipeline->pipe.crtc);
Hm, again this doesn't look like real vblank, but only a page-flip done event. If that's correct then please don't use the vblank machinery, but just store the event internally (protected with your own private spinlock) and send it out using drm_crtc_send_vblank_event directly. No calls to arm_vblank_event or any of the other vblank infrastructure should be needed.
Also please remove the drm_vblank_init() call, since your hw doesn't really have vblanks. And exposing vblanks to userspace without implementing them is confusing.
Quoted 45 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +45
-0+} + +static void display_send_page_flip (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *old_plane_state) +{ +struct drm_plane_state *plane_state =drm_atomic_get_new_plane_state ( + old_plane_state->state, &pipe->plane); + +/* +* If old_plane_state->fb is NULL and plane_state->fb is not, +* then this is an atomic commit which will enable display. +* If old_plane_state->fb is not NULL and plane_state->fb is, +* then this is an atomic commit which will disable display. +* Ignore these and do not send page flip as this framebuffer will be +* sent to the backend as a part of display_set_config call. +*/ +if (old_plane_state->fb && plane_state->fb) { +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe); +struct xen_drm_front_drm_info *drm_info = pipeline->drm_info; +int ret; + + ret = drm_info->front_ops->page_flip (drm_info->front_info, + pipeline->index, +xen_drm_front_fb_to_cookie (plane_state->fb)); + pipeline->pgflip_last_error = ret; +if (ret) { +DRM_ERROR ("Failed to send page flip request to backend: %d\n" , ret); +/* +* As we are at commit stage the DRM core will anyways +* wait for the vblank and knows nothing about our +* failure. The best we can do is to handle +* vblank now, so there is no vblank/flip_done +* time outs +*/ +drm_crtc_handle_vblank (&pipeline->pipe.crtc); + } + } +} + +static int display_prepare_fb (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *plane_state) +{ +struct xen_drm_front_drm_pipeline *pipeline = +to_xen_drm_pipeline (pipe);
drivers/gpu/drm/xen/xen_drm_front_kms.c line 207
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +10
-0+ +if (pipeline->pgflip_last_error) { +int ret; + +/* if previous page flip didn't succeed then report the error */ + ret = pipeline->pgflip_last_error; +/* and let us try to page flip next time */ + pipeline->pgflip_last_error =0 ; +return ret; + }
Nope, this isn't how the uapi works. If your flips fail then we might need to add some error status thing to the drm events, but you can't make the next flip fail.
-Daniel
Quoted 135 lines
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +92
-0+return drm_gem_fb_prepare_fb (&pipe->plane, plane_state); +} + +static void display_update (struct drm_simple_display_pipe *pipe, +struct drm_plane_state *old_plane_state) +{ +struct drm_crtc *crtc = &pipe->crtc; +struct drm_pending_vblank_event *event; + + event = crtc->state->event; +if (event) { +struct drm_device *dev = crtc->dev; +unsigned long flags; + + crtc->state->event =NULL ; + +spin_lock_irqsave (&dev->event_lock, flags); +if (drm_crtc_vblank_get (crtc) ==0 ) +drm_crtc_arm_vblank_event (crtc, event); +else +drm_crtc_send_vblank_event (crtc, event); +spin_unlock_irqrestore (&dev->event_lock, flags); + } +/* +* Send page flip request to the backend *after* we have event armed/ +* sent above, so on page flip done event from the backend we can +* deliver it while handling vblank. +*/ +display_send_page_flip (pipe, old_plane_state); +} + +static const struct drm_simple_display_pipe_funcs display_funcs = { + .enable = display_enable, + .disable = display_disable, + .prepare_fb = display_prepare_fb, + .update = display_update, +}; + +static int display_pipe_init (struct xen_drm_front_drm_info *drm_info, +int index,struct xen_drm_front_cfg_connector *cfg, +struct xen_drm_front_drm_pipeline *pipeline) +{ +struct drm_device *dev = drm_info->drm_dev; +const uint32_t *formats; +int format_count; +int ret; + + pipeline->drm_info = drm_info; + pipeline->index = index; + pipeline->height = cfg->height; + pipeline->width = cfg->width; + + ret =xen_drm_front_conn_init (drm_info, &pipeline->conn); +if (ret) +return ret; + + formats =xen_drm_front_conn_get_formats (&format_count); + +return drm_simple_display_pipe_init (dev, &pipeline->pipe, + &display_funcs, formats, format_count, +NULL , &pipeline->conn); +} + +int xen_drm_front_kms_init (struct xen_drm_front_drm_info *drm_info) +{ +struct drm_device *dev = drm_info->drm_dev; +int i, ret; + +drm_mode_config_init (dev); + + dev->mode_config.min_width =0 ; + dev->mode_config.min_height =0 ; + dev->mode_config.max_width =4095 ; + dev->mode_config.max_height =2047 ; + dev->mode_config.funcs = &mode_config_funcs; + +for (i =0 ; i < drm_info->cfg->num_connectors; i++) { +struct xen_drm_front_cfg_connector *cfg = + &drm_info->cfg->connectors[i]; +struct xen_drm_front_drm_pipeline *pipeline = + &drm_info->pipeline[i]; + + ret =display_pipe_init (drm_info, i, cfg, pipeline); +if (ret) { +drm_mode_config_cleanup (dev); +return ret; + } + } + +drm_mode_config_reset (dev); +return 0 ; +}drivers/gpu/drm/xen/xen_drm_front_kms.h new file +30
-0@@ -0,0 +1,30 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_KMS_H_ +#define __XEN_DRM_FRONT_KMS_H_ + +#include "xen_drm_front_drv.h" + +int xen_drm_front_kms_init (struct xen_drm_front_drm_info *drm_info); + +void xen_drm_front_kms_on_frame_done ( +struct xen_drm_front_drm_pipeline *pipeline, +uint64_t fb_cookie); + +#endif /* __XEN_DRM_FRONT_KMS_H_ */ Signature · 6 lines
2.7.4 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Signature · 8 lines
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ Xen-devel mailing list [email protected] https://lists.xenproject.org/mailman/listinfo/xen-devel
PATCH 7/9 drm/xen-front: Implement KMS/connector handling
In reply to Oleksandr AndrushchenkoFrom: Oleksandr Andrushchenko <[email protected]>
Implement kernel modesetiing/connector handling using DRM simple KMS helper pipeline:
- implement KMS part of the driver with the help of DRM simple pipepline helper which is possible due to the fact that the para-virtualized driver only supports a single (primary) plane:
- initialize connectors according to XenStore configuration
- handle frame done events from the backend
- generate vblank events
- create and destroy frame buffers and propagate those to the backend
- propagate set/reset mode configuration to the backend on display enable/disable callbacks
- send page flip request to the backend and implement logic for reporting backend IO errors on prepare fb callback
- implement virtual connector handling:
- support only pixel formats suitable for single plane modes
- make sure the connector is always connected
- support a single video mode as per para-virtualized driver configuration
--- drivers/gpu/drm/xen/Makefile | 2 + drivers/gpu/drm/xen/xen_drm_front_conn.c | 125 +++++++++++++ drivers/gpu/drm/xen/xen_drm_front_conn.h | 35 ++++ drivers/gpu/drm/xen/xen_drm_front_drv.c | 15 ++ drivers/gpu/drm/xen/xen_drm_front_drv.h | 12 ++ drivers/gpu/drm/xen/xen_drm_front_kms.c | 299 +++++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_kms.h | 30 ++++ 7 files changed, 518 insertions(+) create mode 100644 drivers/gpu/drm/xen/xen_drm_front_conn.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_conn.h create mode 100644 drivers/gpu/drm/xen/xen_drm_front_kms.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_kms.h
drivers/gpu/drm/xen/Makefile +2 -0
@@ -2,6 +2,8 @@ drm_xen_front-objs := xen_drm_front.o \ xen_drm_front_drv.o \ + xen_drm_front_kms.o \ + xen_drm_front_conn.o \ xen_drm_front_evtchnl.o \ xen_drm_front_shbuf.o \ xen_drm_front_cfg.o
drivers/gpu/drm/xen/xen_drm_front_conn.c new file +125 -0
125 lines not on this page · raw message
drivers/gpu/drm/xen/xen_drm_front_conn.h new file +35 -0
@@ -0,0 +1,35 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_CONN_H_ +#define __XEN_DRM_FRONT_CONN_H_ + +#include <drm/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_encoder.h> + +#include <linux/wait.h> + +struct xen_drm_front_drm_info ; + +const uint32_t *xen_drm_front_conn_get_formats (int *format_count); + +int xen_drm_front_conn_init (struct xen_drm_front_drm_info *drm_info, +struct drm_connector *connector); + +#endif /* __XEN_DRM_FRONT_CONN_H_ */
drivers/gpu/drm/xen/xen_drm_front_drv.c +15 -0
@@ -23,6 +23,7 @@#include "xen_drm_front.h" #include "xen_drm_front_cfg.h" #include "xen_drm_front_drv.h" +#include "xen_drm_front_kms.h" static int dumb_create (struct drm_file *filp,struct drm_device *dev,struct drm_mode_create_dumb *args)
@@ -41,6 +42,13 @@ static void free_object(struct drm_gem_object *obj)static void on_frame_done (struct platform_device *pdev,int conn_idx,uint64_t fb_cookie) { +struct xen_drm_front_drm_info *drm_info =platform_get_drvdata (pdev); + +if (unlikely (conn_idx >= drm_info->cfg->num_connectors)) +return ; + +xen_drm_front_kms_on_frame_done (&drm_info->pipeline[conn_idx], + fb_cookie); }static void lastclose (struct drm_device *dev)
@@ -157,6 +165,12 @@ int xen_drm_front_drv_probe(struct platform_device *pdev,return ret; } + ret =xen_drm_front_kms_init (drm_info); +if (ret) { +DRM_ERROR ("Failed to initialize DRM/KMS, ret %d\n" , ret); + goto fail_modeset; + } + dev->irq_enabled =1 ; ret =drm_dev_register (dev,0 );
@@ -172,6 +186,7 @@ int xen_drm_front_drv_probe(struct platform_device *pdev, fail_register:drm_dev_unregister (dev); +fail_modeset:drm_mode_config_cleanup (dev);return ret; }
drivers/gpu/drm/xen/xen_drm_front_drv.h +12 -0
@@ -20,14 +20,24 @@#define __XEN_DRM_FRONT_DRV_H_#include <drm/drmP.h> +#include <drm/drm_simple_kms_helper.h> #include "xen_drm_front.h" #include "xen_drm_front_cfg.h" +#include "xen_drm_front_conn.h" struct xen_drm_front_drm_pipeline {struct xen_drm_front_drm_info *drm_info;int index; + +struct drm_simple_display_pipe pipe; + +struct drm_connector conn; +/* these are only for connector mode checking */ +int width, height; +/* last backend error seen on page flip */ +int pgflip_last_error; };struct xen_drm_front_drm_info {
@@ -35,6 +45,8 @@ struct xen_drm_front_drm_info {struct xen_drm_front_ops *front_ops;struct drm_device *drm_dev;struct xen_drm_front_cfg *cfg; + +struct xen_drm_front_drm_pipeline pipeline[XEN_DRM_FRONT_MAX_CRTCS ]; }; static inline uint64_t xen_drm_front_fb_to_cookie(
drivers/gpu/drm/xen/xen_drm_front_kms.c new file +299 -0
299 lines not on this page · raw message
drivers/gpu/drm/xen/xen_drm_front_kms.h new file +30 -0
@@ -0,0 +1,30 @@ +/* +* Xen para-virtual DRM device +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* Copyright (C) 2016-2018 EPAM Systems Inc. +* +* Author: Oleksandr Andrushchenko <[email protected]> +*/ + +#ifndef __XEN_DRM_FRONT_KMS_H_ +#define __XEN_DRM_FRONT_KMS_H_ + +#include "xen_drm_front_drv.h" + +int xen_drm_front_kms_init (struct xen_drm_front_drm_info *drm_info); + +void xen_drm_front_kms_on_frame_done ( +struct xen_drm_front_drm_pipeline *pipeline, +uint64_t fb_cookie); + +#endif /* __XEN_DRM_FRONT_KMS_H_ */
Signature · 7 lines
2.7.4 _______________________________________________ Xen-devel mailing list [email protected] https://lists.xenproject.org/mailman/listinfo/xen-devel
PATCH 8/9 drm/xen-front: Implement GEM operations
In reply to Oleksandr AndrushchenkoFrom: Oleksandr Andrushchenko <[email protected]>
Implement GEM handling depending on driver mode of operation:
depending on the requirements for the para-virtualized environment, namely requirements dictated by the accompanying DRM/(v)GPU drivers running in both host and guest environments, number of operating modes of para-virtualized display driver are supported:
- display buffers can be allocated by either frontend driver or backend
- display buffers can be allocated to be contiguous in memory or not
Note! Frontend driver itself has no dependency on contiguous memory for its operation.
1. Buffers allocated by the frontend driver.
The below modes of operation are configured at compile-time via frontend driver's kernel configuration.
1.1. Front driver configured to use GEM CMA helpers
This use-case is useful when used with accompanying DRM/vGPU driver in guest domain which was designed to only work with contiguous buffers, e.g. DRM driver based on GEM CMA helpers: such drivers can only import contiguous PRIME buffers, thus requiring frontend driver to provide such. In order to implement this mode of operation para-virtualized frontend driver can be configured to use GEM CMA helpers.
1.2. Front driver doesn't use GEM CMA
If accompanying drivers can cope with non-contiguous memory then, to lower pressure on CMA subsystem of the kernel, driver can allocate buffers from system memory.
Note! If used with accompanying DRM/(v)GPU drivers this mode of operation may require IOMMU support on the platform, so accompanying DRM/vGPU hardware can still reach display buffer memory while importing PRIME buffers from the frontend driver.
2. Buffers allocated by the backend
This mode of operation is run-time configured via guest domain configuration through XenStore entries.
For systems which do not provide IOMMU support, but having specific requirements for display buffers it is possible to allocate such buffers at backend side and share those with the frontend.
For example, if host domain is 1:1 mapped and has DRM/GPU hardware expecting physically contiguous memory, this allows implementing zero-copying use-cases.
Note! Configuration options 1.1 (contiguous display buffers) and 2 (backend allocated buffers) are not supported at the same time.
--- drivers/gpu/drm/xen/Kconfig | 13 + drivers/gpu/drm/xen/Makefile | 6 + drivers/gpu/drm/xen/xen_drm_front.h | 74 ++++++ drivers/gpu/drm/xen/xen_drm_front_drv.c | 80 ++++++- drivers/gpu/drm/xen/xen_drm_front_drv.h | 1 + drivers/gpu/drm/xen/xen_drm_front_gem.c | 360 ++++++++++++++++++++++++++++ drivers/gpu/drm/xen/xen_drm_front_gem.h | 46 ++++ drivers/gpu/drm/xen/xen_drm_front_gem_cma.c | 93 +++++++ 8 files changed, 667 insertions(+), 6 deletions(-) create mode 100644 drivers/gpu/drm/xen/xen_drm_front_gem.c create mode 100644 drivers/gpu/drm/xen/xen_drm_front_gem.h create mode 100644 drivers/gpu/drm/xen/xen_drm_front_gem_cma.c
drivers/gpu/drm/xen/Kconfig +13 -0
@@ -15,3 +15,16 @@ config DRM_XEN_FRONTEND help Choose this option if you want to enable a para-virtualized frontend DRM/KMS driver for Xen guest OSes. + +config DRM_XEN_FRONTEND_CMA + bool "Use DRM CMA to allocate dumb buffers" + depends on DRM_XEN_FRONTEND + select DRM_KMS_CMA_HELPER + select DRM_GEM_CMA_HELPER + help + Use DRM CMA helpers to allocate display buffers. + This is useful for the use-cases when guest driver needs to + share or export buffers to other drivers which only expect + contiguous buffers. + Note: in this mode driver cannot use buffers allocated + by the backend.
drivers/gpu/drm/xen/Makefile +6 -0
@@ -8,4 +8,10 @@ drm_xen_front-objs := xen_drm_front.o \ xen_drm_front_shbuf.o \ xen_drm_front_cfg.o +ifeq ($(CONFIG_DRM_XEN_FRONTEND_CMA),y) + drm_xen_front-objs += xen_drm_front_gem_cma.o +else + drm_xen_front-objs += xen_drm_front_gem.o +endif + obj-$(CONFIG_DRM_XEN_FRONTEND) += drm_xen_front.o
drivers/gpu/drm/xen/xen_drm_front.h +74 -0
80 lines not on this page · raw message
drivers/gpu/drm/xen/xen_drm_front_drv.c +74 -6
130 lines not on this page · raw message
drivers/gpu/drm/xen/xen_drm_front_drv.h +1 -0
@@ -43,6 +43,7 @@ struct xen_drm_front_drm_pipeline {struct xen_drm_front_drm_info {struct xen_drm_front_info *front_info;struct xen_drm_front_ops *front_ops; +const struct xen_drm_front_gem_ops *gem_ops;struct drm_device *drm_dev;struct xen_drm_front_cfg *cfg;
drivers/gpu/drm/xen/xen_drm_front_gem.c new file +360 -0
360 lines not on this page · raw message
drivers/gpu/drm/xen/xen_drm_front_gem.h new file +46 -0
46 lines not on this page · raw message
drivers/gpu/drm/xen/xen_drm_front_gem_cma.c new file +93 -0
93 lines not on this page · raw message
Signature · 6 lines
2.7.4 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 8/9] drm/xen-front: Implement GEM operations
Quoted 7 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front_gem.c new file +7
-0+static struct xen_gem_object *gem_create (struct drm_device *dev,size_t size) +{ +struct xen_drm_front_drm_info *drm_info = dev->dev_private; +struct xen_gem_object *xen_obj; +int ret; + + size =round_up (size,PAGE_SIZE );
drivers/gpu/drm/xen/xen_drm_front_gem.c line 105
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c new file +10
-0+ xen_obj =gem_create_obj (dev, size); +if (IS_ERR_OR_NULL (xen_obj)) +return xen_obj; + +if (drm_info->cfg->be_alloc) { +/* +* backend will allocate space for this buffer, so +* only allocate array of pointers to pages +*/ + xen_obj->be_alloc = true;
If be_alloc is a flag (which I am not sure about) --- should it be set to true *after* you've successfully allocated your things?
drivers/gpu/drm/xen/xen_drm_front_gem.c line 113
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c new file +8
-0+ ret =gem_alloc_pages_array (xen_obj, size); +if (ret <0 ) { +gem_free_pages_array (xen_obj); + goto fail; + } + + ret =alloc_xenballooned_pages (xen_obj->num_pages, + xen_obj->pages);
Why are you allocating balloon pages?
-boris
Quoted 18 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c new file +17
-0+if (ret <0 ) { +DRM_ERROR ("Cannot allocate %zu ballooned pages: %d\n" , + xen_obj->num_pages, ret); + goto fail; + } + +return xen_obj; + } +/* +* need to allocate backing pages now, so we can share those +* with the backend +*/ + xen_obj->num_pages =DIV_ROUND_UP (size,PAGE_SIZE ); + xen_obj->pages =drm_gem_get_pages (&xen_obj->base); +if (IS_ERR_OR_NULL (xen_obj->pages)) { + ret =PTR_ERR (xen_obj->pages); + xen_obj->pages =NULL ;
drivers/gpu/drm/xen/xen_drm_front_gem.c line 140
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c new file +10
-0+ goto fail; + } + +return xen_obj; + +fail: +DRM_ERROR ("Failed to allocate buffer with size %zu\n" , size); +return ERR_PTR (ret); +} +
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Oleksandr Andrushchenko
maintainerRe: [PATCH 8/9] drm/xen-front: Implement GEM operations
Quoted 12 lines · Boris Ostrovsky
Quoted 11 lines · Oleksandr Andrushchenko
drivers/gpu/drm/xen/xen_drm_front_gem.c new file +11
-0+static struct xen_gem_object *gem_create (struct drm_device *dev,size_t size) +{ +struct xen_drm_front_drm_info *drm_info = dev->dev_private; +struct xen_gem_object *xen_obj; +int ret; + + size =round_up (size,PAGE_SIZE ); + xen_obj =gem_create_obj (dev, size); +if (IS_ERR_OR_NULL (xen_obj)) +return xen_obj; +
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c line 105
Quoted 6 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c new file +6
-0+if (drm_info->cfg->be_alloc) { +/* +* backend will allocate space for this buffer, so +* only allocate array of pointers to pages +*/ + xen_obj->be_alloc = true;If
be_allocis a flag (which I am not sure about) --- should it be set to true *after* you've successfully allocated your things?
this is a configuration option telling about the way the buffer gets allocated: either by the frontend or backend (be_alloc -> buffer allocated by the backend)
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c line 113
Quoted 9 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c new file +8
-0+ ret =gem_alloc_pages_array (xen_obj, size); +if (ret <0 ) { +gem_free_pages_array (xen_obj); + goto fail; + } + + ret =alloc_xenballooned_pages (xen_obj->num_pages, + xen_obj->pages);Why are you allocating balloon pages?
in this use-case we map pages provided by the backend (yes, I know this can be a problem from both security POV and that DomU can die holding pages of Dom0 forever:
but still it is a configuration option, so user decides if her use-case needs this and takes responsibility for such a decision).
Please see description of the buffering modes in xen_drm_front.h specifically for backend allocated buffers:
*******************************************************************************
* 2. Buffers allocated by the backend
*******************************************************************************
*
* This mode of operation is run-time configured via guest domain configuration
* through XenStore entries.
*
* For systems which do not provide IOMMU support, but having specific
* requirements for display buffers it is possible to allocate such buffers
* at backend side and share those with the frontend.
* For example, if host domain is 1:1 mapped and has DRM/GPU hardware expecting
* physically contiguous memory, this allows implementing zero-copying
* use-cases.
Quoted 23 lines
-boris
Quoted 20 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c new file +20
-0+if (ret <0 ) { +DRM_ERROR ("Cannot allocate %zu ballooned pages: %d\n" , + xen_obj->num_pages, ret); + goto fail; + } + +return xen_obj; + } +/* +* need to allocate backing pages now, so we can share those +* with the backend +*/ + xen_obj->num_pages =DIV_ROUND_UP (size,PAGE_SIZE ); + xen_obj->pages =drm_gem_get_pages (&xen_obj->base); +if (IS_ERR_OR_NULL (xen_obj->pages)) { + ret =PTR_ERR (xen_obj->pages); + xen_obj->pages =NULL ; + goto fail; + } +
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c line 140
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c new file +7
-0+return xen_obj; + +fail: +DRM_ERROR ("Failed to allocate buffer with size %zu\n" , size); +return ERR_PTR (ret); +} +
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Re: [PATCH 8/9] drm/xen-front: Implement GEM operations
Quoted 22 lines · Oleksandr Andrushchenko
Quoted 13 lines · Boris Ostrovsky
Quoted 12 lines · Oleksandr Andrushchenko
+static struct
xen_gem_object*gem_create(structdrm_device*dev,size_tsize)drivers/gpu/drm/xen/xen_drm_front_gem.c new file +10
-0+{ +struct xen_drm_front_drm_info *drm_info = dev->dev_private; +struct xen_gem_object *xen_obj; +int ret; + + size =round_up (size,PAGE_SIZE ); + xen_obj =gem_create_obj (dev, size); +if (IS_ERR_OR_NULL (xen_obj)) +return xen_obj; +Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c line 105
Quoted 6 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c new file +6
-0+if (drm_info->cfg->be_alloc) { +/* +* backend will allocate space for this buffer, so +* only allocate array of pointers to pages +*/ + xen_obj->be_alloc = true;If
be_allocis a flag (which I am not sure about) --- should it be set to true *after* you've successfully allocated your things?
Quoted 3 lines
this is a configuration option telling about the way the buffer gets allocated: either by the frontend or backend (
be_alloc-> buffer allocated by the backend)
I can see how drm_info->cfg->be_alloc might be a configuration option but xen_obj->be_alloc is set here and that's not how configuration options typically behave.
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c new file +8
-0+ ret =gem_alloc_pages_array (xen_obj, size); +if (ret <0 ) { +gem_free_pages_array (xen_obj); + goto fail; + } + + ret =alloc_xenballooned_pages (xen_obj->num_pages, + xen_obj->pages);
Quoted 7 lines
Quoted 1 line
Why are you allocating balloon pages?
in this use-case we map pages provided by the backend (yes, I know this can be a problem from both security POV and that DomU can die holding pages of Dom0 forever:
but still it is a configuration option, so user decides if her use-case needs this and takes responsibility for such a decision).
Perhaps I am missing something here but when you say "I know this can be a problem from both security POV ..." then there is something wrong with your solution.
-boris
Quoted 54 lines
Please see description of the buffering modes in
xen_drm_front.hspecifically for backend allocated buffers:
******************************************************************************** 2. Buffers allocated by the backend
********************************************************************************
* This mode of operation is run-time configured via guest domain
configuration
* through XenStore entries.
*
* For systems which do not provide IOMMU support, but having specific
* requirements for display buffers it is possible to allocate such
buffers
* at backend side and share those with the frontend.
* For example, if host domain is 1:1 mapped and has DRM/GPU hardware
expecting
* physically contiguous memory, this allows implementing zero-copying
* use-cases.Quoted 31 lines
-boris
Quoted 28 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c new file +27
-0+if (ret <0 ) { +DRM_ERROR ("Cannot allocate %zu ballooned pages: %d\n" , + xen_obj->num_pages, ret); + goto fail; + } + +return xen_obj; + } +/* +* need to allocate backing pages now, so we can share those +* with the backend +*/ + xen_obj->num_pages =DIV_ROUND_UP (size,PAGE_SIZE ); + xen_obj->pages =drm_gem_get_pages (&xen_obj->base); +if (IS_ERR_OR_NULL (xen_obj->pages)) { + ret =PTR_ERR (xen_obj->pages); + xen_obj->pages =NULL ; + goto fail; + } + +return xen_obj; + +fail: +DRM_ERROR ("Failed to allocate buffer with size %zu\n" , size); +return ERR_PTR (ret); +} +
Re: [PATCH 8/9] drm/xen-front: Implement GEM operations
Quoted 23 lines · Boris Ostrovsky
Quoted 22 lines · Oleksandr Andrushchenko
Quoted 21 lines · Boris Ostrovsky
Quoted 8 lines · Oleksandr Andrushchenko
+static struct
xen_gem_object*gem_create(structdrm_device*dev,size_tsize)drivers/gpu/drm/xen/xen_drm_front_gem.c new file +6
-0+{ +struct xen_drm_front_drm_info *drm_info = dev->dev_private; +struct xen_gem_object *xen_obj; +int ret; + + size =round_up (size,PAGE_SIZE );drivers/gpu/drm/xen/xen_drm_front_gem.c line 105
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c new file +10
-0+ xen_obj =gem_create_obj (dev, size); +if (IS_ERR_OR_NULL (xen_obj)) +return xen_obj; + +if (drm_info->cfg->be_alloc) { +/* +* backend will allocate space for this buffer, so +* only allocate array of pointers to pages +*/ + xen_obj->be_alloc = true;If
be_allocis a flag (which I am not sure about) --- should it be set to true *after* you've successfully allocated your things?
Quoted 7 lines
Quoted 3 lines
this is a configuration option telling about the way the buffer gets allocated: either by the frontend or backend (
be_alloc-> buffer allocated by the backend)I can see how
drm_info->cfg->be_allocmight be a configuration option butxen_obj->be_allocis set here and that's not how configuration options typically behave.
you are right, I will put be_alloc down the code and will slightly rework error handling for this function
Quoted 17 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c new file +8
-0+ ret =gem_alloc_pages_array (xen_obj, size); +if (ret <0 ) { +gem_free_pages_array (xen_obj); + goto fail; + } + + ret =alloc_xenballooned_pages (xen_obj->num_pages, + xen_obj->pages);Quoted 7 lines
Quoted 1 line
Why are you allocating balloon pages?
in this use-case we map pages provided by the backend (yes, I know this can be a problem from both security POV and that DomU can die holding pages of Dom0 forever:
but still it is a configuration option, so user decides if her use-case needs this and takes responsibility for such a decision).
Quoted 3 lines
Perhaps I am missing something here but when you say "I know this can be a problem from both security POV ..." then there is something wrong with your solution.
well, in this scenario there are actually 2 concerns:
1. If DomU dies the pages/grants from Dom0/DomD cannot be reclaimed back
2. Misbehaving guest may send too many requests to the backend exhausting grant references and memory of Dom0/DomD (this is the only concern from security POV). Please see [1]
But, we are focusing on embedded use-cases,
so those systems we use are not that "dynamic" with respect to 2).
Namely: we have fixed number of domains and their functionality is well known, so we can do rather precise assumption on resource usage. This is why I try to warn on such a use-case and rely on the end user who understands the caveats
I'll probably add more precise description of this use-case clarifying what is that security POV, so there is no confusion
Hope this explanation answers your questions
Quoted 45 lines
-boris
Quoted 43 lines
Please see description of the buffering modes in
xen_drm_front.hspecifically for backend allocated buffers:
******************************************************************************** 2. Buffers allocated by the backend
********************************************************************************
* This mode of operation is run-time configured via guest domain
configuration
* through XenStore entries.
*
* For systems which do not provide IOMMU support, but having specific
* requirements for display buffers it is possible to allocate such
buffers
* at backend side and share those with the frontend.
* For example, if host domain is 1:1 mapped and has DRM/GPU hardware
expecting
* physically contiguous memory, this allows implementing zero-copying
* use-cases.Quoted 22 lines
-boris
Quoted 20 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c new file +20
-0+if (ret <0 ) { +DRM_ERROR ("Cannot allocate %zu ballooned pages: %d\n" , + xen_obj->num_pages, ret); + goto fail; + } + +return xen_obj; + } +/* +* need to allocate backing pages now, so we can share those +* with the backend +*/ + xen_obj->num_pages =DIV_ROUND_UP (size,PAGE_SIZE ); + xen_obj->pages =drm_gem_get_pages (&xen_obj->base); +if (IS_ERR_OR_NULL (xen_obj->pages)) { + ret =PTR_ERR (xen_obj->pages); + xen_obj->pages =NULL ; + goto fail; + } +
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c line 140
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c new file +7
-0+return xen_obj; + +fail: +DRM_ERROR ("Failed to allocate buffer with size %zu\n" , size); +return ERR_PTR (ret); +} +
Thank you,
Oleksandr
[1] https://lists.xenproject.org/archives/html/xen-devel/2017-07/msg03100.html
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 8/9] drm/xen-front: Implement GEM operations
Quoted 31 lines · Oleksandr Andrushchenko
Quoted 20 lines · Boris Ostrovsky
Quoted 11 lines · Oleksandr Andrushchenko
Quoted 10 lines · Boris Ostrovsky
Quoted 8 lines · Oleksandr Andrushchenko
+ ret =
gem_alloc_pages_array(xen_obj, size); + if (ret < 0) {
+gem_free_pages_array(xen_obj);
+ goto fail;
+ }
+
+ ret =alloc_xenballooned_pages(xen_obj->num_pages, + xen_obj->pages);Quoted 7 lines
Quoted 1 line
Why are you allocating balloon pages?
in this use-case we map pages provided by the backend (yes, I know this can be a problem from both security POV and that DomU can die holding pages of Dom0 forever:
but still it is a configuration option, so user decides if her use-case needs this and takes responsibility for such a decision).Quoted 3 lines
Perhaps I am missing something here but when you say "I know this can be a problem from both security POV ..." then there is something wrong with your solution.
well, in this scenario there are actually 2 concerns:
1. If DomU dies the pages/grants from Dom0/DomD cannot be reclaimed back
2. Misbehaving guest may send too many requests to the backend exhausting grant references and memory of Dom0/DomD (this is the only concern from security POV). Please see [1]
Quoted 6 lines
But, we are focusing on embedded use-cases,
so those systems we use are not that "dynamic" with respect to 2).
Namely: we have fixed number of domains and their functionality is well known, so we can do rather precise assumption on resource usage. This is why I try to warn on such a use-case and rely on the end user who understands the caveats
How will dom0/backend know whether or not to trust the front end (and thus whether or not to provide provide pages to it)? Will there be something in xenstore, for example, to indicate such trusted frontends?
-boris
Quoted 63 lines
I'll probably add more precise description of this use-case clarifying what is that security POV, so there is no confusion
Hope this explanation answers your questions
Quoted 47 lines
-boris
Quoted 45 lines
Please see description of the buffering modes in
xen_drm_front.hspecifically for backend allocated buffers:
******************************************************************************** 2. Buffers allocated by the backend
********************************************************************************
* This mode of operation is run-time configured via guest domain configuration
* through XenStore entries.
*
* For systems which do not provide IOMMU support, but having specific
* requirements for display buffers it is possible to allocate such buffers
* at backend side and share those with the frontend.
* For example, if host domain is 1:1 mapped and has DRM/GPU hardware expecting
* physically contiguous memory, this allows implementing zero-copying
* use-cases.Quoted 22 lines
-boris
Quoted 20 lines
+ if (ret < 0) {
+ DRM_ERROR("Cannot allocate %zu ballooned pages: %d\n", +xen_obj->num_pages, ret);
+ goto fail;
+ }drivers/gpu/drm/xen/xen_drm_front_gem.c new file +15
-0+ + return xen_obj; + } + /* + * need to allocate backing pages now, so we can share those + * with the backend + */ + xen_obj->num_pages = DIV_ROUND_UP(size, PAGE_SIZE); + xen_obj->pages = drm_gem_get_pages(&xen_obj->base); + if (IS_ERR_OR_NULL(xen_obj->pages)) { + ret = PTR_ERR(xen_obj->pages); + xen_obj->pages = NULL; + goto fail; + } +Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c line 140
Quoted 8 lines
+ return
xen_obj;drivers/gpu/drm/xen/xen_drm_front_gem.c new file +6
-0+ +fail: + DRM_ERROR("Failed to allocate buffer with size %zu\n", size); + return ERR_PTR(ret); +} +Thank you,
Oleksandr
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Re: [PATCH 8/9] drm/xen-front: Implement GEM operations
In reply to Oleksandr AndrushchenkoQuoted 31 lines · Oleksandr Andrushchenko
Quoted 20 lines · Boris Ostrovsky
Quoted 11 lines · Oleksandr Andrushchenko
Quoted 10 lines · Boris Ostrovsky
Quoted 8 lines · Oleksandr Andrushchenko
+ ret =
gem_alloc_pages_array(xen_obj, size); + if (ret < 0) {
+gem_free_pages_array(xen_obj);
+ goto fail;
+ }
+
+ ret =alloc_xenballooned_pages(xen_obj->num_pages, + xen_obj->pages);Quoted 7 lines
Quoted 1 line
Why are you allocating balloon pages?
in this use-case we map pages provided by the backend (yes, I know this can be a problem from both security POV and that DomU can die holding pages of Dom0 forever:
but still it is a configuration option, so user decides if her use-case needs this and takes responsibility for such a decision).Quoted 3 lines
Perhaps I am missing something here but when you say "I know this can be a problem from both security POV ..." then there is something wrong with your solution.
well, in this scenario there are actually 2 concerns:
1. If DomU dies the pages/grants from Dom0/DomD cannot be reclaimed back
2. Misbehaving guest may send too many requests to the backend exhausting grant references and memory of Dom0/DomD (this is the only concern from security POV). Please see [1]
Quoted 6 lines
But, we are focusing on embedded use-cases,
so those systems we use are not that "dynamic" with respect to 2).
Namely: we have fixed number of domains and their functionality is well known, so we can do rather precise assumption on resource usage. This is why I try to warn on such a use-case and rely on the end user who understands the caveats
How will dom0/backend know whether or not to trust the front end (and thus whether or not to provide provide pages to it)? Will there be something in xenstore, for example, to indicate such trusted frontends?
-boris
Quoted 66 lines
I'll probably add more precise description of this use-case clarifying what is that security POV, so there is no confusion
Hope this explanation answers your questions
Quoted 47 lines
-boris
Quoted 45 lines
Please see description of the buffering modes in
xen_drm_front.hspecifically for backend allocated buffers:
******************************************************************************** 2. Buffers allocated by the backend
********************************************************************************
* This mode of operation is run-time configured via guest domain configuration
* through XenStore entries.
*
* For systems which do not provide IOMMU support, but having specific
* requirements for display buffers it is possible to allocate such buffers
* at backend side and share those with the frontend.
* For example, if host domain is 1:1 mapped and has DRM/GPU hardware expecting
* physically contiguous memory, this allows implementing zero-copying
* use-cases.Quoted 22 lines
-boris
Quoted 20 lines
+ if (ret < 0) {
+ DRM_ERROR("Cannot allocate %zu ballooned pages: %d\n", +xen_obj->num_pages, ret);
+ goto fail;
+ }drivers/gpu/drm/xen/xen_drm_front_gem.c new file +15
-0+ + return xen_obj; + } + /* + * need to allocate backing pages now, so we can share those + * with the backend + */ + xen_obj->num_pages = DIV_ROUND_UP(size, PAGE_SIZE); + xen_obj->pages = drm_gem_get_pages(&xen_obj->base); + if (IS_ERR_OR_NULL(xen_obj->pages)) { + ret = PTR_ERR(xen_obj->pages); + xen_obj->pages = NULL; + goto fail; + } +Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c line 140
Quoted 8 lines
+ return
xen_obj;drivers/gpu/drm/xen/xen_drm_front_gem.c new file +6
-0+ +fail: + DRM_ERROR("Failed to allocate buffer with size %zu\n", size); + return ERR_PTR(ret); +} +Thank you,
Oleksandr[1]
https://lists.xenproject.org/archives/html/xen-devel/2017-07/msg03100.html
Re: [PATCH 8/9] drm/xen-front: Implement GEM operations
Quoted 37 lines · Boris Ostrovsky
Quoted 29 lines · Oleksandr Andrushchenko
Quoted 18 lines · Boris Ostrovsky
Quoted 10 lines · Oleksandr Andrushchenko
Quoted 9 lines · Boris Ostrovsky
Quoted 8 lines · Oleksandr Andrushchenko
+ ret =
gem_alloc_pages_array(xen_obj, size); + if (ret < 0) {
+gem_free_pages_array(xen_obj);
+ goto fail;
+ }
+
+ ret =alloc_xenballooned_pages(xen_obj->num_pages, + xen_obj->pages);Quoted 7 lines
Quoted 1 line
Why are you allocating balloon pages?
in this use-case we map pages provided by the backend (yes, I know this can be a problem from both security POV and that DomU can die holding pages of Dom0 forever:
but still it is a configuration option, so user decides if her use-case needs this and takes responsibility for such a decision).Quoted 3 lines
Perhaps I am missing something here but when you say "I know this can be a problem from both security POV ..." then there is something wrong with your solution.
well, in this scenario there are actually 2 concerns:
1. If DomU dies the pages/grants from Dom0/DomD cannot be reclaimed back
2. Misbehaving guest may send too many requests to the backend exhausting grant references and memory of Dom0/DomD (this is the only concern from security POV). Please see [1]Quoted 6 lines
But, we are focusing on embedded use-cases,
so those systems we use are not that "dynamic" with respect to 2).
Namely: we have fixed number of domains and their functionality is well known, so we can do rather precise assumption on resource usage. This is why I try to warn on such a use-case and rely on the end user who understands the caveats
Quoted 3 lines
How will dom0/backend know whether or not to trust the front end (and thus whether or not to provide provide pages to it)? Will there be something in xenstore, for example, to indicate such trusted frontends?
Exactly, there is a dedicated xl configuration option available [1] for vdispl:
"be-alloc=BOOLEAN
Indicates if backend can be a buffer provider/allocator for this domain. See display protocol for details."
Thus, one can configure this per domain for trusted ones in corresponding xl configuration files
Quoted 68 lines
-boris
Quoted 65 lines
I'll probably add more precise description of this use-case clarifying what is that security POV, so there is no confusion
Hope this explanation answers your questions
Quoted 47 lines
-boris
Quoted 45 lines
Please see description of the buffering modes in
xen_drm_front.hspecifically for backend allocated buffers:*******************************************************************************
* 2. Buffers allocated by the backend
*******************************************************************************
*
* This mode of operation is run-time configured via guest domain
configuration
* through XenStore entries.
*
* For systems which do not provide IOMMU support, but having specific
* requirements for display buffers it is possible to allocate such
buffers
* at backend side and share those with the frontend.
* For example, if host domain is 1:1 mapped and has DRM/GPU hardware
expecting
* physically contiguous memory, this allows implementing zero-copying
* use-cases.Quoted 22 lines
-boris
Quoted 20 lines
+ if (ret < 0) {
+ DRM_ERROR("Cannot allocate %zu ballooned pages: %d\n", +xen_obj->num_pages, ret);
+ goto fail;
+ }drivers/gpu/drm/xen/xen_drm_front_gem.c new file +15
-0+ + return xen_obj; + } + /* + * need to allocate backing pages now, so we can share those + * with the backend + */ + xen_obj->num_pages = DIV_ROUND_UP(size, PAGE_SIZE); + xen_obj->pages = drm_gem_get_pages(&xen_obj->base); + if (IS_ERR_OR_NULL(xen_obj->pages)) { + ret = PTR_ERR(xen_obj->pages); + xen_obj->pages = NULL; + goto fail; + } +Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c line 140
Quoted 8 lines
+ return
xen_obj;drivers/gpu/drm/xen/xen_drm_front_gem.c new file +6
-0+ +fail: + DRM_ERROR("Failed to allocate buffer with size %zu\n", size); + return ERR_PTR(ret); +} +Thank you,
Oleksandr[1]
https://lists.xenproject.org/archives/html/xen-devel/2017-07/msg03100.html
[1] https://xenbits.xen.org/docs/4.10-testing/man/xl.cfg.5.html
Indicates if backend can be a buffer provider/allocator for this domain. See display protocol for details.
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 8/9] drm/xen-front: Implement GEM operations
In reply to Boris OstrovskyQuoted 37 lines · Boris Ostrovsky
Quoted 29 lines · Oleksandr Andrushchenko
Quoted 18 lines · Boris Ostrovsky
Quoted 10 lines · Oleksandr Andrushchenko
Quoted 9 lines · Boris Ostrovsky
Quoted 8 lines · Oleksandr Andrushchenko
+ ret =
gem_alloc_pages_array(xen_obj, size); + if (ret < 0) {
+gem_free_pages_array(xen_obj);
+ goto fail;
+ }
+
+ ret =alloc_xenballooned_pages(xen_obj->num_pages, + xen_obj->pages);Quoted 7 lines
Quoted 1 line
Why are you allocating balloon pages?
in this use-case we map pages provided by the backend (yes, I know this can be a problem from both security POV and that DomU can die holding pages of Dom0 forever:
but still it is a configuration option, so user decides if her use-case needs this and takes responsibility for such a decision).Quoted 3 lines
Perhaps I am missing something here but when you say "I know this can be a problem from both security POV ..." then there is something wrong with your solution.
well, in this scenario there are actually 2 concerns:
1. If DomU dies the pages/grants from Dom0/DomD cannot be reclaimed back
2. Misbehaving guest may send too many requests to the backend exhausting grant references and memory of Dom0/DomD (this is the only concern from security POV). Please see [1]Quoted 6 lines
But, we are focusing on embedded use-cases,
so those systems we use are not that "dynamic" with respect to 2).
Namely: we have fixed number of domains and their functionality is well known, so we can do rather precise assumption on resource usage. This is why I try to warn on such a use-case and rely on the end user who understands the caveats
Quoted 3 lines
How will dom0/backend know whether or not to trust the front end (and thus whether or not to provide provide pages to it)? Will there be something in xenstore, for example, to indicate such trusted frontends?
Exactly, there is a dedicated xl configuration option available [1] for vdispl:
"be-alloc=BOOLEAN
Indicates if backend can be a buffer provider/allocator for this domain. See display protocol for details."
Thus, one can configure this per domain for trusted ones in corresponding xl configuration files
Quoted 68 lines
-boris
Quoted 65 lines
I'll probably add more precise description of this use-case clarifying what is that security POV, so there is no confusion
Hope this explanation answers your questions
Quoted 47 lines
-boris
Quoted 45 lines
Please see description of the buffering modes in
xen_drm_front.hspecifically for backend allocated buffers:*******************************************************************************
* 2. Buffers allocated by the backend
*******************************************************************************
*
* This mode of operation is run-time configured via guest domain
configuration
* through XenStore entries.
*
* For systems which do not provide IOMMU support, but having specific
* requirements for display buffers it is possible to allocate such
buffers
* at backend side and share those with the frontend.
* For example, if host domain is 1:1 mapped and has DRM/GPU hardware
expecting
* physically contiguous memory, this allows implementing zero-copying
* use-cases.Quoted 22 lines
-boris
Quoted 20 lines
+ if (ret < 0) {
+ DRM_ERROR("Cannot allocate %zu ballooned pages: %d\n", +xen_obj->num_pages, ret);
+ goto fail;
+ }drivers/gpu/drm/xen/xen_drm_front_gem.c new file +15
-0+ + return xen_obj; + } + /* + * need to allocate backing pages now, so we can share those + * with the backend + */ + xen_obj->num_pages = DIV_ROUND_UP(size, PAGE_SIZE); + xen_obj->pages = drm_gem_get_pages(&xen_obj->base); + if (IS_ERR_OR_NULL(xen_obj->pages)) { + ret = PTR_ERR(xen_obj->pages); + xen_obj->pages = NULL; + goto fail; + } +Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c line 140
Quoted 8 lines
+ return
xen_obj;drivers/gpu/drm/xen/xen_drm_front_gem.c new file +6
-0+ +fail: + DRM_ERROR("Failed to allocate buffer with size %zu\n", size); + return ERR_PTR(ret); +} +Thank you,
Oleksandr[1]
https://lists.xenproject.org/archives/html/xen-devel/2017-07/msg03100.html
[1] https://xenbits.xen.org/docs/4.10-testing/man/xl.cfg.5.html
Indicates if backend can be a buffer provider/allocator for this domain. See display protocol for details.
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel
Re: [PATCH 8/9] drm/xen-front: Implement GEM operations
In reply to Boris OstrovskyQuoted 23 lines · Boris Ostrovsky
Quoted 22 lines · Oleksandr Andrushchenko
Quoted 21 lines · Boris Ostrovsky
Quoted 8 lines · Oleksandr Andrushchenko
+static struct
xen_gem_object*gem_create(structdrm_device*dev,size_tsize)drivers/gpu/drm/xen/xen_drm_front_gem.c new file +6
-0+{ +struct xen_drm_front_drm_info *drm_info = dev->dev_private; +struct xen_gem_object *xen_obj; +int ret; + + size =round_up (size,PAGE_SIZE );drivers/gpu/drm/xen/xen_drm_front_gem.c line 105
Quoted 10 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c new file +10
-0+ xen_obj =gem_create_obj (dev, size); +if (IS_ERR_OR_NULL (xen_obj)) +return xen_obj; + +if (drm_info->cfg->be_alloc) { +/* +* backend will allocate space for this buffer, so +* only allocate array of pointers to pages +*/ + xen_obj->be_alloc = true;If
be_allocis a flag (which I am not sure about) --- should it be set to true *after* you've successfully allocated your things?
Quoted 7 lines
Quoted 3 lines
this is a configuration option telling about the way the buffer gets allocated: either by the frontend or backend (
be_alloc-> buffer allocated by the backend)I can see how
drm_info->cfg->be_allocmight be a configuration option butxen_obj->be_allocis set here and that's not how configuration options typically behave.
you are right, I will put be_alloc down the code and will slightly rework error handling for this function
Quoted 17 lines
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c new file +8
-0+ ret =gem_alloc_pages_array (xen_obj, size); +if (ret <0 ) { +gem_free_pages_array (xen_obj); + goto fail; + } + + ret =alloc_xenballooned_pages (xen_obj->num_pages, + xen_obj->pages);Quoted 7 lines
Quoted 1 line
Why are you allocating balloon pages?
in this use-case we map pages provided by the backend (yes, I know this can be a problem from both security POV and that DomU can die holding pages of Dom0 forever:
but still it is a configuration option, so user decides if her use-case needs this and takes responsibility for such a decision).
Quoted 3 lines
Perhaps I am missing something here but when you say "I know this can be a problem from both security POV ..." then there is something wrong with your solution.
well, in this scenario there are actually 2 concerns:
1. If DomU dies the pages/grants from Dom0/DomD cannot be reclaimed back
2. Misbehaving guest may send too many requests to the backend exhausting grant references and memory of Dom0/DomD (this is the only concern from security POV). Please see [1]
But, we are focusing on embedded use-cases,
so those systems we use are not that "dynamic" with respect to 2).
Namely: we have fixed number of domains and their functionality is well known, so we can do rather precise assumption on resource usage. This is why I try to warn on such a use-case and rely on the end user who understands the caveats
I'll probably add more precise description of this use-case clarifying what is that security POV, so there is no confusion
Hope this explanation answers your questions
Quoted 45 lines
-boris
Quoted 43 lines
Please see description of the buffering modes in
xen_drm_front.hspecifically for backend allocated buffers:
******************************************************************************** 2. Buffers allocated by the backend
********************************************************************************
* This mode of operation is run-time configured via guest domain
configuration
* through XenStore entries.
*
* For systems which do not provide IOMMU support, but having specific
* requirements for display buffers it is possible to allocate such
buffers
* at backend side and share those with the frontend.
* For example, if host domain is 1:1 mapped and has DRM/GPU hardware
expecting
* physically contiguous memory, this allows implementing zero-copying
* use-cases.Quoted 22 lines
-boris
Quoted 20 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c new file +20
-0+if (ret <0 ) { +DRM_ERROR ("Cannot allocate %zu ballooned pages: %d\n" , + xen_obj->num_pages, ret); + goto fail; + } + +return xen_obj; + } +/* +* need to allocate backing pages now, so we can share those +* with the backend +*/ + xen_obj->num_pages =DIV_ROUND_UP (size,PAGE_SIZE ); + xen_obj->pages =drm_gem_get_pages (&xen_obj->base); +if (IS_ERR_OR_NULL (xen_obj->pages)) { + ret =PTR_ERR (xen_obj->pages); + xen_obj->pages =NULL ; + goto fail; + } +
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c line 140
Quoted 8 lines
drivers/gpu/drm/xen/xen_drm_front_gem.c new file +7
-0+return xen_obj; + +fail: +DRM_ERROR ("Failed to allocate buffer with size %zu\n" , size); +return ERR_PTR (ret); +} +
Thank you,
Oleksandr
[1] https://lists.xenproject.org/archives/html/xen-devel/2017-07/msg03100.html
_______________________________________________
Xen-devel mailing list
[email protected]
https://lists.xenproject.org/mailman/listinfo/xen-devel