Skip to contentSkip to conversation

drm: add simpledrm driver

PATCH In review David Herrmann 5 participants 29 messages Sep 2, 2016 – Mar 12, 2021

Subsystems (14)
DRM drivers x86 DRM misc Intel i915 +10 more subsystems
lore
Share & tools
lore
#0 lore raw

v5 cover drm: add simpledrm driver

Hey

On request of Noralf, I picked up the patches and prepared v5. Works fine with Xorg, if configured according to:

    https://lists.freedesktop.org/archives/dri-devel/2014-January/052777.html

If anyone knows how to make Xorg pick it up dynamically without such a static configuration, please let me know.

Thanks
David

David Herrmann (7):
x86/sysfb: add support for 64bit EFI lfb_base x86/sysfb: fix lfb_size calculation of/platform: expose of_platform_device_destroy()
video: add generic framebuffer eviction
drm: switch to sysfb_evict_conflicts()
drm: add SimpleDRM driver
drm/simpledrm: add fbdev fallback support

 MAINTAINERS                                  |   6 +
 arch/x86/kernel/sysfb_simplefb.c             |  39 ++-
 drivers/gpu/drm/Kconfig                      |   3 +
 drivers/gpu/drm/Makefile                     |   1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c      |  24 +-
 drivers/gpu/drm/bochs/bochs_drv.c            |  19 +-
 drivers/gpu/drm/i915/i915_drv.c              |  73 +---
 drivers/gpu/drm/mgag200/mgag200_drv.c        |  27 +-
 drivers/gpu/drm/mgag200/mgag200_main.c       |   9 -
 drivers/gpu/drm/nouveau/nouveau_drm.c        |  33 +-
 drivers/gpu/drm/radeon/radeon_drv.c          |  24 +-
 drivers/gpu/drm/simpledrm/Kconfig            |  19 ++
 drivers/gpu/drm/simpledrm/Makefile           |   9 +
 drivers/gpu/drm/simpledrm/simpledrm.h        |  91 +++++
 drivers/gpu/drm/simpledrm/simpledrm_damage.c | 194 +++++++++++
 drivers/gpu/drm/simpledrm/simpledrm_drv.c    | 477 +++++++++++++++++++++++++++
 drivers/gpu/drm/simpledrm/simpledrm_fbdev.c  | 143 ++++++++
 drivers/gpu/drm/simpledrm/simpledrm_gem.c    | 109 ++++++
 drivers/gpu/drm/simpledrm/simpledrm_kms.c    | 270 +++++++++++++++
 drivers/gpu/drm/simpledrm/simpledrm_of.c     | 265 +++++++++++++++
 drivers/gpu/drm/sun4i/sun4i_drv.c            |  24 +-
 drivers/gpu/drm/vc4/vc4_drv.c                |  25 +-
 drivers/gpu/drm/virtio/virtgpu_drm_bus.c     |  24 +-
 drivers/of/platform.c                        |  35 +-
 drivers/video/Kconfig                        |   4 +
 drivers/video/Makefile                       |   1 +
 drivers/video/sysfb.c                        | 327 ++++++++++++++++++
 include/linux/of_platform.h                  |   1 +
 include/linux/sysfb.h                        |  34 ++
 29 files changed, 2054 insertions(+), 256 deletions(-)
 create mode 100644 drivers/gpu/drm/simpledrm/Kconfig
 create mode 100644 drivers/gpu/drm/simpledrm/Makefile
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm.h
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_damage.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_drv.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_fbdev.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_gem.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_kms.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_of.c
 create mode 100644 drivers/video/sysfb.c
 create mode 100644 include/linux/sysfb.h
Signature · 6 lines
2.9.3

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
#1 lore raw

PATCH v5 1/7 x86/sysfb: add support for 64bit EFI lfb_base

The screen_info object was extended to support 64bit lfb_base addresses in:

commit ae2ee627dc87a70910de91b791b3cd0e9c6facdd
Author: Matt Fleming <[email protected]>
Date: Tue Aug 25 16:32:55 2015 +0100

efifb: Add support for 64-bit frame buffer addresses

However, the x86 simple-framebuffer setup code never made use of it. Fix it to properly assemble and verify the lfb_base before advertising simple-framebuffer devices.

In particular, this means if VIDEO_CAPABILITY_64BIT_BASE is set, the screen_info->ext_lfb_base field will contain the upper 32bit of the actual lfb_base. Make sure the address is not 0 (i.e., unset), as well as does not overflow the physical address type.

---
 arch/x86/kernel/sysfb_simplefb.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)
arch/x86/kernel/sysfb_simplefb.c +16 -2
index 764a29f..35b8641 100644
@@ -67,6 +67,20 @@ __init int create_simplefb(const struct screen_info *si,
 	struct platform_device *pd;
 	struct resource res;
 	unsigned long len;
+	u64 base;
+
+	/*
+	 * If the 64BIT_BASE capability is set, ext_lfb_base will contain the
+	 * upper half of the base address. Assemble the address, then make sure
+	 * it is valid and we can actually access it.
+	 */
+	base = si->lfb_base;
+	if (si->capabilities & VIDEO_CAPABILITY_64BIT_BASE)
+		base |= (u64)si->ext_lfb_base << 32;
+	if (!base || (u64)(resource_size_t)base != base) {
+		printk(KERN_DEBUG "sysfb: inaccessible VRAM base\n");
+		return -EINVAL;
+	}
 
 	/* don't use lfb_size as it may contain the whole VMEM instead of only
 	 * the part that is occupied by the framebuffer */
@@ -81,8 +95,8 @@ __init int create_simplefb(const struct screen_info *si,
 	memset(&res, 0, sizeof(res));
 	res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
 	res.name = simplefb_resname;
-	res.start = si->lfb_base;
-	res.end = si->lfb_base + len - 1;
+	res.start = base;
+	res.end = res.start + len - 1;
 	if (res.end <= res.start)
 		return -EINVAL;
 
Signature · 6 lines
2.9.3

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Reviewed-by on v5 1/7
#2 lore raw

Re: [PATCH v5 1/7] x86/sysfb: add support for 64bit EFI lfb_base

Quoted 13 lines · David Herrmann

The screen_info object was extended to support 64bit lfb_base addresses in:

commit ae2ee627dc87a70910de91b791b3cd0e9c6facdd
Author: Matt Fleming <[email protected]>
Date: Tue Aug 25 16:32:55 2015 +0100

efifb: Add support for 64-bit frame buffer addresses

However, the x86 simple-framebuffer setup code never made use of it. Fix it to properly assemble and verify the lfb_base before advertising simple-framebuffer devices.

Quoted 6 lines

In particular, this means if VIDEO_CAPABILITY_64BIT_BASE is set, the screen_info->ext_lfb_base field will contain the upper 32bit of the actual lfb_base. Make sure the address is not 0 (i.e., unset), as well as does not overflow the physical address type.

Quoted 43 lines
---
 arch/x86/kernel/sysfb_simplefb.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)
arch/x86/kernel/sysfb_simplefb.c +16 -3
index 764a29f..35b8641 100644
@@ -67,6 +67,20 @@ __init int create_simplefb(const struct screen_info *si,
        struct platform_device *pd;
        struct resource res;
        unsigned long len;
+       u64 base;
+
+       /*
+        * If the 64BIT_BASE capability is set, ext_lfb_base will contain the
+        * upper half of the base address. Assemble the address, then make sure
+        * it is valid and we can actually access it.
+        */
+       base = si->lfb_base;
+       if (si->capabilities & VIDEO_CAPABILITY_64BIT_BASE)
+               base |= (u64)si->ext_lfb_base << 32;
+       if (!base || (u64)(resource_size_t)base != base) {
+               printk(KERN_DEBUG "sysfb: inaccessible VRAM base\n");
+               return -EINVAL;
+       }
 
        /* don't use lfb_size as it may contain the whole VMEM instead of only
         * the part that is occupied by the framebuffer */
@@ -81,8 +95,8 @@ __init int create_simplefb(const struct screen_info *si,
        memset(&res, 0, sizeof(res));
        res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
        res.name = simplefb_resname;
-       res.start = si->lfb_base;
-       res.end = si->lfb_base + len - 1;
+       res.start = base;
+       res.end = res.start + len - 1;
        if (res.end <= res.start)
                return -EINVAL;
 
--

2.9.3

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

#3 lore raw

PATCH v5 2/7 x86/sysfb: fix lfb_size calculation

In reply to David Herrmann

The screen_info.lfb_size field is shifted by 16 bits *only* in case of VBE. This has historical reasons since VBE advertised it similarly. However, in case of EFI framebuffers, the size is no longer shifted. Fix the x86 simple-framebuffer setup code to use the correct size in the non-VBE case.

While at it, avoid variable abbreviations and rename 'len' to 'length', and use the correct types matching the screen_info definition.

---
 arch/x86/kernel/sysfb_simplefb.c | 25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)
arch/x86/kernel/sysfb_simplefb.c +17 -8
index 35b8641..85195d4 100644
@@ -66,8 +66,8 @@ __init int create_simplefb(const struct screen_info *si,
 {
 	struct platform_device *pd;
 	struct resource res;
-	unsigned long len;
-	u64 base;
+	u64 base, size;
+	u32 length;
 
 	/*
 	 * If the 64BIT_BASE capability is set, ext_lfb_base will contain the
@@ -82,11 +82,20 @@ __init int create_simplefb(const struct screen_info *si,
 		return -EINVAL;
 	}
 
-	/* don't use lfb_size as it may contain the whole VMEM instead of only
-	 * the part that is occupied by the framebuffer */
-	len = mode->height * mode->stride;
-	len = PAGE_ALIGN(len);
-	if (len > (u64)si->lfb_size << 16) {
+	/*
+	 * Don't use lfb_size as IORESOURCE size, since it may contain the
+	 * entire VMEM, and thus require huge mappings. Use just the part we
+	 * need, that is, the part where the framebuffer is located. But verify
+	 * that it does not exceed the advertised VMEM.
+	 * Note that in case of VBE, the lfb_size is shifted by 16 bits for
+	 * historical reasons.
+	 */
+	size = si->lfb_size;
+	if (si->orig_video_isVGA == VIDEO_TYPE_VLFB)
+		size <<= 16;
+	length = mode->height * mode->stride;
+	length = PAGE_ALIGN(length);
+	if (length > size) {
 		printk(KERN_WARNING "sysfb: VRAM smaller than advertised\n");
 		return -EINVAL;
 	}
@@ -96,7 +105,7 @@ __init int create_simplefb(const struct screen_info *si,
 	res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
 	res.name = simplefb_resname;
 	res.start = base;
-	res.end = res.start + len - 1;
+	res.end = res.start + length - 1;
 	if (res.end <= res.start)
 		return -EINVAL;
 
Signature · 6 lines
2.9.3

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Reviewed-by on v5 2/7
#4 lore raw

Re: [PATCH v5 2/7] x86/sysfb: fix lfb_size calculation

Quoted 10 lines · David Herrmann

The screen_info.lfb_size field is shifted by 16 bits *only* in case of VBE. This has historical reasons since VBE advertised it similarly. However, in case of EFI framebuffers, the size is no longer shifted. Fix the x86 simple-framebuffer setup code to use the correct size in the non-VBE case.

While at it, avoid variable abbreviations and rename 'len' to 'length', and use the correct types matching the screen_info definition.

Quoted 57 lines
---
 arch/x86/kernel/sysfb_simplefb.c | 25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)
arch/x86/kernel/sysfb_simplefb.c +17 -9
index 35b8641..85195d4 100644
@@ -66,8 +66,8 @@ __init int create_simplefb(const struct screen_info *si,
 {
        struct platform_device *pd;
        struct resource res;
-       unsigned long len;
-       u64 base;
+       u64 base, size;
+       u32 length;
 
        /*
         * If the 64BIT_BASE capability is set, ext_lfb_base will contain the
@@ -82,11 +82,20 @@ __init int create_simplefb(const struct screen_info *si,
                return -EINVAL;
        }
 
-       /* don't use lfb_size as it may contain the whole VMEM instead of only
-        * the part that is occupied by the framebuffer */
-       len = mode->height * mode->stride;
-       len = PAGE_ALIGN(len);
-       if (len > (u64)si->lfb_size << 16) {
+       /*
+        * Don't use lfb_size as IORESOURCE size, since it may contain the
+        * entire VMEM, and thus require huge mappings. Use just the part we
+        * need, that is, the part where the framebuffer is located. But verify
+        * that it does not exceed the advertised VMEM.
+        * Note that in case of VBE, the lfb_size is shifted by 16 bits for
+        * historical reasons.
+        */
+       size = si->lfb_size;
+       if (si->orig_video_isVGA == VIDEO_TYPE_VLFB)
+               size <<= 16;
+       length = mode->height * mode->stride;
+       length = PAGE_ALIGN(length);
+       if (length > size) {
                printk(KERN_WARNING "sysfb: VRAM smaller than advertised\n");
                return -EINVAL;
        }
@@ -96,7 +105,7 @@ __init int create_simplefb(const struct screen_info *si,
        res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
        res.name = simplefb_resname;
        res.start = base;
-       res.end = res.start + len - 1;
+       res.end = res.start + length - 1;
        if (res.end <= res.start)
                return -EINVAL;
 
--

2.9.3

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

#5 lore raw

PATCH v5 3/7 of/platform: expose of_platform_device_destroy()

In reply to David Herrmann

We already expose of_platform_device_create(), but give the caller no chance to revert its effect. Make sure we also provide the counterpart of_platform_device_destroy().

This requires a small refactoring, since so far the internal destructor is used as iterator to for_each_device(), but we don't want to expose it with the "void *data" parameter. So provide of_platform_device_depopulate() as new iterator, which calls into of_platform_device_destroy().

While at it, drop the unused 'children_left' argument by of_platform_notify(). It is a left-over that somehow was never removed.

---
 drivers/of/platform.c       | 35 ++++++++++++++++++++++++++---------
 include/linux/of_platform.h |  1 +
 2 files changed, 27 insertions(+), 9 deletions(-)
drivers/of/platform.c +26 -9
index f39ccd5..f9bb563 100644
@@ -524,15 +524,18 @@ static int __init of_platform_default_populate_init(void)
 arch_initcall_sync(of_platform_default_populate_init);
 #endif
 
-static int of_platform_device_destroy(struct device *dev, void *data)
+/**
+ * of_platform_device_destroy - unregister an of_device
+ * @dev: device to unregister
+ *
+ * This is the inverse operation of of_platform_device_create(). It unregisters
+ * the passed device, if registered.
+ */
+void of_platform_device_destroy(struct device *dev)
 {
 	/* Do not touch devices not populated from the device tree */
 	if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED))
-		return 0;
-
-	/* Recurse for any nodes that were treated as busses */
-	if (of_node_check_flag(dev->of_node, OF_POPULATED_BUS))
-		device_for_each_child(dev, NULL, of_platform_device_destroy);
+		return;
 
 	if (dev->bus == &platform_bus_type)
 		platform_device_unregister(to_platform_device(dev));
@@ -544,6 +547,20 @@ static int of_platform_device_destroy(struct device *dev, void *data)
 	of_dma_deconfigure(dev);
 	of_node_clear_flag(dev->of_node, OF_POPULATED);
 	of_node_clear_flag(dev->of_node, OF_POPULATED_BUS);
+}
+EXPORT_SYMBOL(of_platform_device_destroy);
+
+static int of_platform_device_depopulate(struct device *dev, void *data)
+{
+	/* Do not touch devices not populated from the device tree */
+	if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED))
+		return 0;
+
+	/* Recurse for any nodes that were treated as busses */
+	if (of_node_check_flag(dev->of_node, OF_POPULATED_BUS))
+		device_for_each_child(dev, NULL, of_platform_device_depopulate);
+
+	of_platform_device_destroy(dev);
 	return 0;
 }
 
@@ -562,7 +579,8 @@ static int of_platform_device_destroy(struct device *dev, void *data)
 void of_platform_depopulate(struct device *parent)
 {
 	if (parent->of_node && of_node_check_flag(parent->of_node, OF_POPULATED_BUS)) {
-		device_for_each_child(parent, NULL, of_platform_device_destroy);
+		device_for_each_child(parent, NULL,
+				      of_platform_device_depopulate);
 		of_node_clear_flag(parent->of_node, OF_POPULATED_BUS);
 	}
 }
@@ -574,7 +592,6 @@ static int of_platform_notify(struct notifier_block *nb,
 {
 	struct of_reconfig_data *rd = arg;
 	struct platform_device *pdev_parent, *pdev;
-	bool children_left;
 
 	switch (of_reconfig_get_state_change(action, rd)) {
 	case OF_RECONFIG_CHANGE_ADD:
@@ -612,7 +629,7 @@ static int of_platform_notify(struct notifier_block *nb,
 			return NOTIFY_OK;	/* no? not meant for us */
 
 		/* unregister takes one ref away */
-		of_platform_device_destroy(&pdev->dev, &children_left);
+		of_platform_device_depopulate(&pdev->dev, NULL);
 
 		/* and put the reference of the find */
 		of_dev_put(pdev);
include/linux/of_platform.h +1 -0
index 956a100..a9017d3 100644
@@ -63,6 +63,7 @@ extern struct platform_device *of_find_device_by_node(struct device_node *np);
 extern struct platform_device *of_platform_device_create(struct device_node *np,
 						   const char *bus_id,
 						   struct device *parent);
+extern void of_platform_device_destroy(struct device *dev);
 
 extern int of_platform_bus_probe(struct device_node *root,
 				 const struct of_device_id *matches,
Signature · 6 lines
2.9.3

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Reviewed-by on v5 3/7
#6 lore raw

Re: [PATCH v5 3/7] of/platform: expose of_platform_device_destroy()

Quoted 10 lines · David Herrmann

We already expose of_platform_device_create(), but give the caller no chance to revert its effect. Make sure we also provide the counterpart of_platform_device_destroy().

This requires a small refactoring, since so far the internal destructor is used as iterator to for_each_device(), but we don't want to expose it with the "void *data" parameter. So provide of_platform_device_depopulate() as new iterator, which calls into of_platform_device_destroy().

Quoted 4 lines

While at it, drop the unused 'children_left' argument by of_platform_notify(). It is a left-over that somehow was never removed.

Quoted 97 lines
---
 drivers/of/platform.c       | 35 ++++++++++++++++++++++++++---------
 include/linux/of_platform.h |  1 +
 2 files changed, 27 insertions(+), 9 deletions(-)
drivers/of/platform.c +26 -9
index f39ccd5..f9bb563 100644
@@ -524,15 +524,18 @@ static int __init of_platform_default_populate_init(void)
 arch_initcall_sync(of_platform_default_populate_init);
 #endif
 
-static int of_platform_device_destroy(struct device *dev, void *data)
+/**
+ * of_platform_device_destroy - unregister an of_device
+ * @dev: device to unregister
+ *
+ * This is the inverse operation of of_platform_device_create(). It unregisters
+ * the passed device, if registered.
+ */
+void of_platform_device_destroy(struct device *dev)
 {
        /* Do not touch devices not populated from the device tree */
        if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED))
-               return 0;
-
-       /* Recurse for any nodes that were treated as busses */
-       if (of_node_check_flag(dev->of_node, OF_POPULATED_BUS))
-               device_for_each_child(dev, NULL, of_platform_device_destroy);
+               return;
 
        if (dev->bus == &platform_bus_type)
                platform_device_unregister(to_platform_device(dev));
@@ -544,6 +547,20 @@ static int of_platform_device_destroy(struct device *dev, void *data)
        of_dma_deconfigure(dev);
        of_node_clear_flag(dev->of_node, OF_POPULATED);
        of_node_clear_flag(dev->of_node, OF_POPULATED_BUS);
+}
+EXPORT_SYMBOL(of_platform_device_destroy);
+
+static int of_platform_device_depopulate(struct device *dev, void *data)
+{
+       /* Do not touch devices not populated from the device tree */
+       if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED))
+               return 0;
+
+       /* Recurse for any nodes that were treated as busses */
+       if (of_node_check_flag(dev->of_node, OF_POPULATED_BUS))
+               device_for_each_child(dev, NULL, of_platform_device_depopulate);
+
+       of_platform_device_destroy(dev);
        return 0;
 }
 
@@ -562,7 +579,8 @@ static int of_platform_device_destroy(struct device *dev, void *data)
 void of_platform_depopulate(struct device *parent)
 {
        if (parent->of_node && of_node_check_flag(parent->of_node, OF_POPULATED_BUS)) {
-               device_for_each_child(parent, NULL, of_platform_device_destroy);
+               device_for_each_child(parent, NULL,
+                                     of_platform_device_depopulate);
                of_node_clear_flag(parent->of_node, OF_POPULATED_BUS);
        }
 }
@@ -574,7 +592,6 @@ static int of_platform_notify(struct notifier_block *nb,
 {
        struct of_reconfig_data *rd = arg;
        struct platform_device *pdev_parent, *pdev;
-       bool children_left;
 
        switch (of_reconfig_get_state_change(action, rd)) {
        case OF_RECONFIG_CHANGE_ADD:
@@ -612,7 +629,7 @@ static int of_platform_notify(struct notifier_block *nb,
                        return NOTIFY_OK;       /* no? not meant for us */
 
                /* unregister takes one ref away */
-               of_platform_device_destroy(&pdev->dev, &children_left);
+               of_platform_device_depopulate(&pdev->dev, NULL);
 
                /* and put the reference of the find */
                of_dev_put(pdev);
include/linux/of_platform.h +1 -1
index 956a100..a9017d3 100644
@@ -63,6 +63,7 @@ extern struct platform_device *of_find_device_by_node(struct device_node *np);
 extern struct platform_device *of_platform_device_create(struct device_node *np,
                                                   const char *bus_id,
                                                   struct device *parent);
+extern void of_platform_device_destroy(struct device *dev);
 
 extern int of_platform_bus_probe(struct device_node *root,
                                 const struct of_device_id *matches,
--

2.9.3

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

#7 lore raw

PATCH v5 4/7 video: add generic framebuffer eviction

In reply to David Herrmann

There are several situations where we want hardware handover from an early boot GFX driver (e.g., vgacon, vesafb, efifb, simplefb) to a full fletched GFX driver (e.g., most DRM drivers). So far, we relied on remove_conflicting_framebuffers() to do this for us, however, this had a bunch of downsides:

o It only removes conflicting fbdev drivers. It does not drop vgacon, early boot console drivers, conflicting DRM drivers, etc.

o It only unloads the fbdev driver, it does not modify the underlying device or resources. In case of "screen_info" drivers (e.g., efifb) this is fine, since no resources are pinned. However, if the driver binds to a platform-device like "simple-framebuffer", we must make sure to unregister that device as well. Otherwise, pinned resources like IORESOURCE_MEM stay around, triggering WARN_ONs if the following driver requests those resources.

o It is only available if CONFIG_FB is selected.

This commit adds a new infrastructure that manages system-framebuffers (short: sysfb). The initial commit provides conflict-resolution for system-framebuffers. At its core it provides sysfb_evict_conflicts(), which implements conflict detection and removal for all known types of GFX driver hand-overs. So far, this includes platform-device removal, fbdev-firmware-device removal, vgacon removal and VBE detection. To further simplify the callers, it also provides helpers to figure out what hand-over to do, based on the device the new drivers binds to:

o PCI drivers can use sysfb_evict_conflicts_pci(), which will figure out the apertures automatically, and does VGA/VBE detection.

o Generic firmware drivers that might be shadowed at any address in memory can use sysfb_evict_conflicts_firmware(), basically removing *all* firmware framebuffers in effect.

This only adds the generic sysfb helpers. No users are converted, yet.

---
 drivers/video/Kconfig  |   4 +
 drivers/video/Makefile |   1 +
 drivers/video/sysfb.c  | 327 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/sysfb.h  |  34 +++++
 4 files changed, 366 insertions(+)
 create mode 100644 drivers/video/sysfb.c
 create mode 100644 include/linux/sysfb.h
drivers/video/Kconfig +4 -0
index 3c20af9..56a8294 100644
@@ -36,6 +36,10 @@ config VIDEOMODE_HELPERS
 config HDMI
 	bool
 
+config SYSFB
+	bool
+	select DUMMY_CONSOLE if VT
+
 if VT
 	source "drivers/video/console/Kconfig"
 endif
drivers/video/Makefile +1 -0
index 9ad3c17..df7bd75 100644
@@ -1,5 +1,6 @@
 obj-$(CONFIG_VGASTATE)            += vgastate.o
 obj-$(CONFIG_HDMI)                += hdmi.o
+obj-$(CONFIG_SYSFB)		  += sysfb.o
 
 obj-$(CONFIG_VT)		  += console/
 obj-$(CONFIG_LOGO)		  += logo/
drivers/video/sysfb.c new file +327 -0

327 lines not on this page · raw message

include/linux/sysfb.h new file +34 -0
new file mode 100644
index 0000000..b67c74a
@@ -0,0 +1,34 @@
+#ifndef __LINUX_SYSFB_H
+#define __LINUX_SYSFB_H
+
+/*
+ * Copyright (C) 2013-2016 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+
+struct apertures_struct;
+struct pci_dev;
+
+enum {
+	SYSFB_EVICT_PLATFORM			= (1U <<  0),
+	SYSFB_EVICT_FBDEV			= (1U <<  1),
+	SYSFB_EVICT_VGACON			= (1U <<  2),
+	SYSFB_EVICT_VBE				= (1U <<  3),
+};
+
+struct sysfb_evict_ctx {
+	struct apertures_struct *ap;
+	unsigned int flags;
+};
+
+int sysfb_evict_conflicts(struct sysfb_evict_ctx *ctx);
+int sysfb_evict_conflicts_firmware(void);
+int sysfb_evict_conflicts_pci(struct pci_dev *pdev);
+
+#endif /* __LINUX_SYSFB_H */
Signature · 6 lines
2.9.3

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Reviewed-by on v5 4/7
#8 lore raw

Re: [PATCH v5 4/7] video: add generic framebuffer eviction

Quoted 31 lines · David Herrmann

There are several situations where we want hardware handover from an early boot GFX driver (e.g., vgacon, vesafb, efifb, simplefb) to a full fletched GFX driver (e.g., most DRM drivers). So far, we relied on remove_conflicting_framebuffers() to do this for us, however, this had a bunch of downsides:

o It only removes conflicting fbdev drivers. It does not drop vgacon, early boot console drivers, conflicting DRM drivers, etc.

o It only unloads the fbdev driver, it does not modify the underlying device or resources. In case of "screen_info" drivers (e.g., efifb) this is fine, since no resources are pinned. However, if the driver binds to a platform-device like "simple-framebuffer", we must make sure to unregister that device as well. Otherwise, pinned resources like IORESOURCE_MEM stay around, triggering WARN_ONs if the following driver requests those resources.

o It is only available if CONFIG_FB is selected.

This commit adds a new infrastructure that manages system-framebuffers (short: sysfb). The initial commit provides conflict-resolution for system-framebuffers. At its core it provides sysfb_evict_conflicts(), which implements conflict detection and removal for all known types of GFX driver hand-overs. So far, this includes platform-device removal, fbdev-firmware-device removal, vgacon removal and VBE detection. To further simplify the callers, it also provides helpers to figure out what hand-over to do, based on the device the new drivers binds to:

o PCI drivers can use sysfb_evict_conflicts_pci(), which will figure out the apertures automatically, and does VGA/VBE detection.

Quoted 7 lines

o Generic firmware drivers that might be shadowed at any address in memory can use sysfb_evict_conflicts_firmware(), basically removing *all* firmware framebuffers in effect.

This only adds the generic sysfb helpers. No users are converted, yet.

Quoted 411 lines
---
 drivers/video/Kconfig  |   4 +
 drivers/video/Makefile |   1 +
 drivers/video/sysfb.c  | 327 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/sysfb.h  |  34 +++++
 4 files changed, 366 insertions(+)
 create mode 100644 drivers/video/sysfb.c
 create mode 100644 include/linux/sysfb.h
drivers/video/Kconfig +4 -0
index 3c20af9..56a8294 100644
@@ -36,6 +36,10 @@ config VIDEOMODE_HELPERS
 config HDMI
        bool
 
+config SYSFB
+       bool
+       select DUMMY_CONSOLE if VT
+
 if VT
        source "drivers/video/console/Kconfig"
 endif
drivers/video/Makefile +1 -0
index 9ad3c17..df7bd75 100644
@@ -1,5 +1,6 @@
 obj-$(CONFIG_VGASTATE)            += vgastate.o
 obj-$(CONFIG_HDMI)                += hdmi.o
+obj-$(CONFIG_SYSFB)              += sysfb.o
 
 obj-$(CONFIG_VT)                 += console/
 obj-$(CONFIG_LOGO)               += logo/
drivers/video/sysfb.c new file +327 -0
new file mode 100644
index 0000000..00585c9
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2013-2016 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ */
+
+#define pr_fmt(fmt) "sysfb: " fmt
+#include <linux/console.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/sysfb.h>
+#include <linux/vt.h>
+
+static bool sysfb_evict_match_resource(struct sysfb_evict_ctx *ctx,
+                                      struct resource *mem)
+{
+       struct aperture *g;
+       unsigned int i;
+
+       for (i = 0; i < ctx->ap->count; ++i) {
+               g = &ctx->ap->ranges[i];
+
+               if (mem->start == g->base)
+                       return true;
+               if (mem->start >= g->base && mem->end < g->base + g->size)
+                       return true;
+               if ((ctx->flags & SYSFB_EVICT_VBE) && mem->start == 0xA0000)
+                       return true;
+       }
+
+       return false;
+}
+
+static int sysfb_evict_platform_device(struct device *dev, void *userdata)
+{
+       struct sysfb_evict_ctx *ctx = userdata;
+       struct platform_device *pdev = to_platform_device(dev);
+       struct resource *mem;
+
+       if (!pdev->name)
+               return 0;
+
+       if (!strcmp(pdev->name, "simple-framebuffer")) {
+               mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+               if (!mem)
+                       return 0;
+               if (!sysfb_evict_match_resource(ctx, mem))
+                       return 0;
+
+#ifdef CONFIG_OF_ADDRESS
+               if (dev->of_node)
+                       of_platform_device_destroy(dev);
+               else
+#endif
+               if (dev_get_platdata(&pdev->dev))
+                       platform_device_del(pdev);
+       }
+
+       return 0;
+}
+
+static int sysfb_evict_platform(struct sysfb_evict_ctx *ctx)
+{
+       /*
+        * Early-boot architecture setup and boot-loarders sometimes create
+        * preliminary platform devices with a generic framebuffer setup. This
+        * allows graphics access during boot-up, without a real graphics
+        * driver loaded. However, once a real graphics driver takes over, we
+        * have to destroy those platform devices. In the legacy fbdev case, we
+        * just used to unload the fbdev driver. However, to make sure any kind
+        * of driver is unloaded, the platform-eviction code here simply
+        * removes any conflicting platform device directly. This causes any
+        * bound driver to be detached, and then removes the device entirely so
+        * it cannot be bound to later on.
+        *
+        * Please note that any such platform device must be registered by
+        * early architecture setup code. If they are registered after regular
+        * GFX drivers, this will fail horribly.
+        */
+
+       static DEFINE_MUTEX(lock);
+       int ret;
+
+       /*
+        * In case of static platform-devices, we must iterate the bus and
+        * remove them manually. We know that we're the only code that might
+        * remove them, so a simple static lock serializes all calls here.
+        */
+       mutex_lock(&lock);
+       ret = bus_for_each_dev(&platform_bus_type, NULL, ctx,
+                              sysfb_evict_platform_device);
+       mutex_unlock(&lock);
+       return ret;
+}
+
+static int sysfb_evict_fbdev(struct sysfb_evict_ctx *ctx)
+{
+       /*
+        * Usually, evicting platform devices should be enough to also trigger
+        * fbdev unloading. However, some legacy devices (e.g., uvesafb) have
+        * no platform devices that can be evicted, so we still fall back to
+        * the legacy fbdev removal code. Note that this only removes fbdev
+        * devices marked as FBINFO_MISC_FIRMWARE. Anything else is left
+        * untouched.
+        *
+        * As usual, this only works if the fbdev device is probed early,
+        * before any real GFX driver wants to take over.
+        */
+
+       int ret = 0;
+
+#ifdef CONFIG_FB
+       ret = remove_conflicting_framebuffers(ctx->ap, "sysfb",
+                                             ctx->flags & SYSFB_EVICT_VBE);
+#endif
+
+       return ret;
+}
+
+static int sysfb_evict_vgacon(struct sysfb_evict_ctx *ctx)
+{
+       /*
+        * The VGACON console driver pokes at VGA registers randomly. If a GFX
+        * driver cannot keep the VGA support alive, it better makes sure to
+        * unload VGACON before probing.
+        *
+        * Unloading VGACON requires us to first force dummycon to take over
+        * from vgacon (but only if vgacon is really in use), followed by a
+        * deregistration of vgacon. Note that this prevents vgacon from being
+        * used again after the GFX driver is unloaded. But that is usually
+        * fine, since VGA state is rarely restored on driver-unload, anyway.
+        *
+        * Note that we rely on VGACON to be probed in early boot (actually
+        * done by ARCH setup code). If it is probed after GFX drivers, this
+        * will fail horribly. You better make sure VGACON is probed early and
+        * GFX drivers are probed as normal modules.
+        */
+
+       int ret = 0;
+
+#ifdef CONFIG_VGA_CONSOLE
+       console_lock();
+       if (con_is_bound(&vga_con))
+               ret = do_take_over_console(&dummy_con, 0,
+                                          MAX_NR_CONSOLES - 1, 1);
+       if (ret == 0) {
+               ret = do_unregister_con_driver(&vga_con);
+               if (ret == -ENODEV) /* ignore "already unregistered" */
+                       ret = 0;
+       }
+       console_unlock();
+#endif
+
+       return ret;
+}
+
+/**
+ * sysfb_evict_conflicts - remove any conflicting system-framebuffers
+ * @ctx:               eviction context
+ *
+ * This function evicts any conflicting system-framebuffers and their bound
+ * drivers, according to the data given in @ctx.
+ *
+ * Depending on @ctx->flags, the following operations are performed:
+ *
+ *   SYSFB_EVICT_PLATFORM: Firmware framebuffer platform devices (eg.,
+ *                         'simple-framebuffer') that overlap @ctx are removed
+ *                         from the system, causing drivers to be unbound.
+ *                         If SYSFB_EVICT_VBE is given, this also affects
+ *                         devices that own the VGA region.
+ *
+ *   SYSFB_EVICT_FBDEV: Any firmware fbdev drivers that overlap @ctx are
+ *                      unloaded.
+ *                      Furthermore, if SYSFB_EVICT_VBE is given as well, any
+ *                      fbdev driver that maps the VGA region is unloaded.
+ *
+ *   SYSFB_EVICT_VGACON: The vgacon console driver is unbound and unregistered.
+ *
+ * This might call into fbdev driver unregistration, or even device_del() on
+ * some buses. Hence, make sure you call this from your top-level
+ * probe-callbacks, rather than with any gfx-subsystem locks held.
+ *
+ * RETURNS:
+ * 0 on success, negative error code on failure.
+ */
+int sysfb_evict_conflicts(struct sysfb_evict_ctx *ctx)
+{
+       int ret;
+
+       if (WARN_ON(!ctx || !ctx->ap))
+               return -EINVAL;
+
+       pr_info("removing conflicts (sysfb%s%s%s%s)\n",
+               (ctx->flags & SYSFB_EVICT_PLATFORM) ? ", platform" : "",
+               (ctx->flags & SYSFB_EVICT_FBDEV) ? ", fbdev" : "",
+               (ctx->flags & SYSFB_EVICT_VGACON) ? ", vgacon" : "",
+               (ctx->flags & SYSFB_EVICT_VBE) ? ", vbe" : "");
+
+       if (ctx->flags & SYSFB_EVICT_PLATFORM) {
+               ret = sysfb_evict_platform(ctx);
+               if (ret < 0)
+                       return ret;
+       }
+
+       if (ctx->flags & SYSFB_EVICT_FBDEV) {
+               ret = sysfb_evict_fbdev(ctx);
+               if (ret < 0)
+                       return ret;
+       }
+
+       if (ctx->flags & SYSFB_EVICT_VGACON) {
+               ret = sysfb_evict_vgacon(ctx);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(sysfb_evict_conflicts);
+
+/**
+ * sysfb_evict_conflicts_firmware() - remove all firmware framebuffers
+ *
+ * This is similar to sysfb_evict_conflicts() but uses a fake aperture spanning
+ * the entire address-space. This is suitable for any GFX driver that just
+ * wants to get rid of all available firmware framebuffers.
+ *
+ * RETURNS:
+ * 0 on success, negative error code on failure.
+ */
+int sysfb_evict_conflicts_firmware(void)
+{
+       struct sysfb_evict_ctx ctx = {};
+       int ret;
+
+       ctx.ap = alloc_apertures(1);
+       if (!ctx.ap)
+               return -ENOMEM;
+
+       ctx.ap->ranges[0].base = 0;
+       ctx.ap->ranges[0].size = ~0;
+
+       ctx.flags |= SYSFB_EVICT_FBDEV | SYSFB_EVICT_PLATFORM;
+       ret = sysfb_evict_conflicts(&ctx);
+
+       kfree(ctx.ap);
+       return ret;
+}
+EXPORT_SYMBOL(sysfb_evict_conflicts_firmware);
+
+#ifdef CONFIG_PCI
+/**
+ * sysfb_evict_conflicts_pci() - remove all system framebuffers conflicting
+ *                               with the given pci device
+ * @pdev:              pci device
+ *
+ * This is similar to sysfb_evict_conflicts() but generates the eviction
+ * context based on the given pci device @pdev.
+ *
+ * RETURNS:
+ * 0 on success, negative error code on failure.
+ */
+int sysfb_evict_conflicts_pci(struct pci_dev *pdev)
+{
+       struct sysfb_evict_ctx ctx = {};
+       size_t i, n, offset;
+       int ret;
+
+       /*
+        * If this device is used as primary VGA device, it is shadowed at the
+        * VBE base address, so make sure to include it in the apertures.
+        */
+       if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
+               ctx.flags |= SYSFB_EVICT_VBE;
+
+       /*
+        * If a device is a VGA device, make sure to kick out vgacon. We cannot
+        * rely on the IORESOURCE_ROM_SHADOW, since vgacon can switch between
+        * vga devices at runtime. So kick out vgacon anyway.
+        */
+       if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
+               ctx.flags |= SYSFB_EVICT_VGACON;
+
+       /*
+        * Allocate apertures for all standard PCI resources. Skip them in case
+        * they are empty.
+        */
+       ctx.ap = alloc_apertures(PCI_STD_RESOURCE_END - PCI_STD_RESOURCES + 1);
+       if (!ctx.ap)
+               return -ENOMEM;
+
+       offset = PCI_STD_RESOURCES;
+       for (n = 0, i = 0; i < ctx.ap->count; ++i) {
+               if (pci_resource_len(pdev, offset + i) < 1)
+                       continue;
+
+               ctx.ap->ranges[n].base = pci_resource_start(pdev, offset + i);
+               ctx.ap->ranges[n].size = pci_resource_len(pdev, offset + i);
+               ++n;
+       }
+       ctx.ap->count = n;
+
+       /*
+        * Evict all matching fbdev devices, VBE devices if they shadow this
+        * device, vgacon if this is a vga device, and platform devices if they
+        * match.
+        */
+       ctx.flags |= SYSFB_EVICT_FBDEV | SYSFB_EVICT_PLATFORM;
+       ret = sysfb_evict_conflicts(&ctx);
+
+       kfree(ctx.ap);
+       return ret;
+}
+EXPORT_SYMBOL(sysfb_evict_conflicts_pci);
+#endif /* CONFIG_PCI */
include/linux/sysfb.h new file +34 -1
new file mode 100644
index 0000000..b67c74a
@@ -0,0 +1,34 @@
+#ifndef __LINUX_SYSFB_H
+#define __LINUX_SYSFB_H
+
+/*
+ * Copyright (C) 2013-2016 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+
+struct apertures_struct;
+struct pci_dev;
+
+enum {
+       SYSFB_EVICT_PLATFORM                    = (1U <<  0),
+       SYSFB_EVICT_FBDEV                       = (1U <<  1),
+       SYSFB_EVICT_VGACON                      = (1U <<  2),
+       SYSFB_EVICT_VBE                         = (1U <<  3),
+};
+
+struct sysfb_evict_ctx {
+       struct apertures_struct *ap;
+       unsigned int flags;
+};
+
+int sysfb_evict_conflicts(struct sysfb_evict_ctx *ctx);
+int sysfb_evict_conflicts_firmware(void);
+int sysfb_evict_conflicts_pci(struct pci_dev *pdev);
+
+#endif /* __LINUX_SYSFB_H */
--

2.9.3

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

#9 lore raw

Re: [PATCH v5 4/7] video: add generic framebuffer eviction

In reply to David Herrmann

Den 02.09.2016 10:22, skrev David Herrmann:

Quoted 124 lines

There are several situations where we want hardware handover from an early boot GFX driver (e.g., vgacon, vesafb, efifb, simplefb) to a full fletched GFX driver (e.g., most DRM drivers). So far, we relied on remove_conflicting_framebuffers() to do this for us, however, this had a bunch of downsides:

o It only removes conflicting fbdev drivers. It does not drop vgacon, early boot console drivers, conflicting DRM drivers, etc.

o It only unloads the fbdev driver, it does not modify the underlying device or resources. In case of "screen_info" drivers (e.g., efifb) this is fine, since no resources are pinned. However, if the driver binds to a platform-device like "simple-framebuffer", we must make sure to unregister that device as well. Otherwise, pinned resources like IORESOURCE_MEM stay around, triggering WARN_ONs if the following driver requests those resources.

o It is only available if CONFIG_FB is selected.

This commit adds a new infrastructure that manages system-framebuffers (short: sysfb). The initial commit provides conflict-resolution for system-framebuffers. At its core it provides sysfb_evict_conflicts(), which implements conflict detection and removal for all known types of GFX driver hand-overs. So far, this includes platform-device removal, fbdev-firmware-device removal, vgacon removal and VBE detection. To further simplify the callers, it also provides helpers to figure out what hand-over to do, based on the device the new drivers binds to:

o PCI drivers can use sysfb_evict_conflicts_pci(), which will figure out the apertures automatically, and does VGA/VBE detection.

o Generic firmware drivers that might be shadowed at any address in memory can use sysfb_evict_conflicts_firmware(), basically removing *all* firmware framebuffers in effect.

This only adds the generic sysfb helpers. No users are converted, yet.

---
  drivers/video/Kconfig  |   4 +
  drivers/video/Makefile |   1 +
  drivers/video/sysfb.c  | 327 +++++++++++++++++++++++++++++++++++++++++++++++++
  include/linux/sysfb.h  |  34 +++++
  4 files changed, 366 insertions(+)

create mode 100644 drivers/video/sysfb.c
create mode 100644 include/linux/sysfb.h

drivers/video/Kconfig +4 -0
index 3c20af9..56a8294 100644
@@ -36,6 +36,10 @@ config VIDEOMODE_HELPERS
  config HDMI
  	bool
 
+config SYSFB
+	bool
+	select DUMMY_CONSOLE if VT
+
  if VT
  	source "drivers/video/console/Kconfig"
  endif
drivers/video/Makefile +1 -0
index 9ad3c17..df7bd75 100644
@@ -1,5 +1,6 @@
  obj-$(CONFIG_VGASTATE)            += vgastate.o
  obj-$(CONFIG_HDMI)                += hdmi.o
+obj-$(CONFIG_SYSFB)		  += sysfb.o
 
  obj-$(CONFIG_VT)		  += console/
  obj-$(CONFIG_LOGO)		  += logo/
drivers/video/sysfb.c new file +45 -0
new file mode 100644
index 0000000..00585c9
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2013-2016 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ */
+
+#define pr_fmt(fmt) "sysfb: " fmt
+#include <linux/console.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/sysfb.h>
+#include <linux/vt.h>
+
+static bool sysfb_evict_match_resource(struct sysfb_evict_ctx *ctx,
+				       struct resource *mem)
+{
+	struct aperture *g;
+	unsigned int i;
+
+	for (i = 0; i < ctx->ap->count; ++i) {
+		g = &ctx->ap->ranges[i];
+
+		if (mem->start == g->base)
+			return true;
+		if (mem->start >= g->base && mem->end < g->base + g->size)
+			return true;
+		if ((ctx->flags & SYSFB_EVICT_VBE) && mem->start == 0xA0000)
+			return true;
+	}
+
+	return false;
+}
+

drivers/video/sysfb.c line 55

Quoted 10 lines
drivers/video/sysfb.c new file +10 -0
+static int sysfb_evict_platform_device(struct device *dev, void *userdata)
+{
+	struct sysfb_evict_ctx *ctx = userdata;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct resource *mem;
+
+	if (!pdev->name)
+		return 0;
+
+	if (!strcmp(pdev->name, "simple-framebuffer")) {

This doesn't work in my case where the device comes from DT and the name also contains the address: pdev->name=1e887000.framebuffer

This is one way of solving it:

       if (!pdev->dev.driver || !pdev->dev.driver->name)
                return 0;

       if (!strcmp(pdev->dev.driver->name, "simple-framebuffer")) {

Noralf.

Quoted 302 lines
drivers/video/sysfb.c new file +272 -0
+		mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		if (!mem)
+			return 0;
+		if (!sysfb_evict_match_resource(ctx, mem))
+			return 0;
+
+#ifdef CONFIG_OF_ADDRESS
+		if (dev->of_node)
+			of_platform_device_destroy(dev);
+		else
+#endif
+		if (dev_get_platdata(&pdev->dev))
+			platform_device_del(pdev);
+	}
+
+	return 0;
+}
+
+static int sysfb_evict_platform(struct sysfb_evict_ctx *ctx)
+{
+	/*
+	 * Early-boot architecture setup and boot-loarders sometimes create
+	 * preliminary platform devices with a generic framebuffer setup. This
+	 * allows graphics access during boot-up, without a real graphics
+	 * driver loaded. However, once a real graphics driver takes over, we
+	 * have to destroy those platform devices. In the legacy fbdev case, we
+	 * just used to unload the fbdev driver. However, to make sure any kind
+	 * of driver is unloaded, the platform-eviction code here simply
+	 * removes any conflicting platform device directly. This causes any
+	 * bound driver to be detached, and then removes the device entirely so
+	 * it cannot be bound to later on.
+	 *
+	 * Please note that any such platform device must be registered by
+	 * early architecture setup code. If they are registered after regular
+	 * GFX drivers, this will fail horribly.
+	 */
+
+	static DEFINE_MUTEX(lock);
+	int ret;
+
+	/*
+	 * In case of static platform-devices, we must iterate the bus and
+	 * remove them manually. We know that we're the only code that might
+	 * remove them, so a simple static lock serializes all calls here.
+	 */
+	mutex_lock(&lock);
+	ret = bus_for_each_dev(&platform_bus_type, NULL, ctx,
+			       sysfb_evict_platform_device);
+	mutex_unlock(&lock);
+	return ret;
+}
+
+static int sysfb_evict_fbdev(struct sysfb_evict_ctx *ctx)
+{
+	/*
+	 * Usually, evicting platform devices should be enough to also trigger
+	 * fbdev unloading. However, some legacy devices (e.g., uvesafb) have
+	 * no platform devices that can be evicted, so we still fall back to
+	 * the legacy fbdev removal code. Note that this only removes fbdev
+	 * devices marked as FBINFO_MISC_FIRMWARE. Anything else is left
+	 * untouched.
+	 *
+	 * As usual, this only works if the fbdev device is probed early,
+	 * before any real GFX driver wants to take over.
+	 */
+
+	int ret = 0;
+
+#ifdef CONFIG_FB
+	ret = remove_conflicting_framebuffers(ctx->ap, "sysfb",
+					      ctx->flags & SYSFB_EVICT_VBE);
+#endif
+
+	return ret;
+}
+
+static int sysfb_evict_vgacon(struct sysfb_evict_ctx *ctx)
+{
+	/*
+	 * The VGACON console driver pokes at VGA registers randomly. If a GFX
+	 * driver cannot keep the VGA support alive, it better makes sure to
+	 * unload VGACON before probing.
+	 *
+	 * Unloading VGACON requires us to first force dummycon to take over
+	 * from vgacon (but only if vgacon is really in use), followed by a
+	 * deregistration of vgacon. Note that this prevents vgacon from being
+	 * used again after the GFX driver is unloaded. But that is usually
+	 * fine, since VGA state is rarely restored on driver-unload, anyway.
+	 *
+	 * Note that we rely on VGACON to be probed in early boot (actually
+	 * done by ARCH setup code). If it is probed after GFX drivers, this
+	 * will fail horribly. You better make sure VGACON is probed early and
+	 * GFX drivers are probed as normal modules.
+	 */
+
+	int ret = 0;
+
+#ifdef CONFIG_VGA_CONSOLE
+	console_lock();
+	if (con_is_bound(&vga_con))
+		ret = do_take_over_console(&dummy_con, 0,
+					   MAX_NR_CONSOLES - 1, 1);
+	if (ret == 0) {
+		ret = do_unregister_con_driver(&vga_con);
+		if (ret == -ENODEV) /* ignore "already unregistered" */
+			ret = 0;
+	}
+	console_unlock();
+#endif
+
+	return ret;
+}
+
+/**
+ * sysfb_evict_conflicts - remove any conflicting system-framebuffers
+ * @ctx:		eviction context
+ *
+ * This function evicts any conflicting system-framebuffers and their bound
+ * drivers, according to the data given in @ctx.
+ *
+ * Depending on @ctx->flags, the following operations are performed:
+ *
+ *   SYSFB_EVICT_PLATFORM: Firmware framebuffer platform devices (eg.,
+ *                         'simple-framebuffer') that overlap @ctx are removed
+ *                         from the system, causing drivers to be unbound.
+ *                         If SYSFB_EVICT_VBE is given, this also affects
+ *                         devices that own the VGA region.
+ *
+ *   SYSFB_EVICT_FBDEV: Any firmware fbdev drivers that overlap @ctx are
+ *                      unloaded.
+ *                      Furthermore, if SYSFB_EVICT_VBE is given as well, any
+ *                      fbdev driver that maps the VGA region is unloaded.
+ *
+ *   SYSFB_EVICT_VGACON: The vgacon console driver is unbound and unregistered.
+ *
+ * This might call into fbdev driver unregistration, or even device_del() on
+ * some buses. Hence, make sure you call this from your top-level
+ * probe-callbacks, rather than with any gfx-subsystem locks held.
+ *
+ * RETURNS:
+ * 0 on success, negative error code on failure.
+ */
+int sysfb_evict_conflicts(struct sysfb_evict_ctx *ctx)
+{
+	int ret;
+
+	if (WARN_ON(!ctx || !ctx->ap))
+		return -EINVAL;
+
+	pr_info("removing conflicts (sysfb%s%s%s%s)\n",
+		(ctx->flags & SYSFB_EVICT_PLATFORM) ? ", platform" : "",
+		(ctx->flags & SYSFB_EVICT_FBDEV) ? ", fbdev" : "",
+		(ctx->flags & SYSFB_EVICT_VGACON) ? ", vgacon" : "",
+		(ctx->flags & SYSFB_EVICT_VBE) ? ", vbe" : "");
+
+	if (ctx->flags & SYSFB_EVICT_PLATFORM) {
+		ret = sysfb_evict_platform(ctx);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (ctx->flags & SYSFB_EVICT_FBDEV) {
+		ret = sysfb_evict_fbdev(ctx);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (ctx->flags & SYSFB_EVICT_VGACON) {
+		ret = sysfb_evict_vgacon(ctx);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(sysfb_evict_conflicts);
+
+/**
+ * sysfb_evict_conflicts_firmware() - remove all firmware framebuffers
+ *
+ * This is similar to sysfb_evict_conflicts() but uses a fake aperture spanning
+ * the entire address-space. This is suitable for any GFX driver that just
+ * wants to get rid of all available firmware framebuffers.
+ *
+ * RETURNS:
+ * 0 on success, negative error code on failure.
+ */
+int sysfb_evict_conflicts_firmware(void)
+{
+	struct sysfb_evict_ctx ctx = {};
+	int ret;
+
+	ctx.ap = alloc_apertures(1);
+	if (!ctx.ap)
+		return -ENOMEM;
+
+	ctx.ap->ranges[0].base = 0;
+	ctx.ap->ranges[0].size = ~0;
+
+	ctx.flags |= SYSFB_EVICT_FBDEV | SYSFB_EVICT_PLATFORM;
+	ret = sysfb_evict_conflicts(&ctx);
+
+	kfree(ctx.ap);
+	return ret;
+}
+EXPORT_SYMBOL(sysfb_evict_conflicts_firmware);
+
+#ifdef CONFIG_PCI
+/**
+ * sysfb_evict_conflicts_pci() - remove all system framebuffers conflicting
+ *                               with the given pci device
+ * @pdev:		pci device
+ *
+ * This is similar to sysfb_evict_conflicts() but generates the eviction
+ * context based on the given pci device @pdev.
+ *
+ * RETURNS:
+ * 0 on success, negative error code on failure.
+ */
+int sysfb_evict_conflicts_pci(struct pci_dev *pdev)
+{
+	struct sysfb_evict_ctx ctx = {};
+	size_t i, n, offset;
+	int ret;
+
+	/*
+	 * If this device is used as primary VGA device, it is shadowed at the
+	 * VBE base address, so make sure to include it in the apertures.
+	 */
+	if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
+		ctx.flags |= SYSFB_EVICT_VBE;
+
+	/*
+	 * If a device is a VGA device, make sure to kick out vgacon. We cannot
+	 * rely on the IORESOURCE_ROM_SHADOW, since vgacon can switch between
+	 * vga devices at runtime. So kick out vgacon anyway.
+	 */
+	if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
+		ctx.flags |= SYSFB_EVICT_VGACON;
+
+	/*
+	 * Allocate apertures for all standard PCI resources. Skip them in case
+	 * they are empty.
+	 */
+	ctx.ap = alloc_apertures(PCI_STD_RESOURCE_END - PCI_STD_RESOURCES + 1);
+	if (!ctx.ap)
+		return -ENOMEM;
+
+	offset = PCI_STD_RESOURCES;
+	for (n = 0, i = 0; i < ctx.ap->count; ++i) {
+		if (pci_resource_len(pdev, offset + i) < 1)
+			continue;
+
+		ctx.ap->ranges[n].base = pci_resource_start(pdev, offset + i);
+		ctx.ap->ranges[n].size = pci_resource_len(pdev, offset + i);
+		++n;
+	}
+	ctx.ap->count = n;
+
+	/*
+	 * Evict all matching fbdev devices, VBE devices if they shadow this
+	 * device, vgacon if this is a vga device, and platform devices if they
+	 * match.
+	 */
+	ctx.flags |= SYSFB_EVICT_FBDEV | SYSFB_EVICT_PLATFORM;
+	ret = sysfb_evict_conflicts(&ctx);
+
+	kfree(ctx.ap);
+	return ret;
+}
+EXPORT_SYMBOL(sysfb_evict_conflicts_pci);
+#endif /* CONFIG_PCI */
include/linux/sysfb.h new file +24 -0
new file mode 100644
index 0000000..b67c74a
@@ -0,0 +1,34 @@
+#ifndef __LINUX_SYSFB_H
+#define __LINUX_SYSFB_H
+
+/*
+ * Copyright (C) 2013-2016 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+
+struct apertures_struct;
+struct pci_dev;
+
+enum {
+	SYSFB_EVICT_PLATFORM			= (1U <<  0),
+	SYSFB_EVICT_FBDEV			= (1U <<  1),
+	SYSFB_EVICT_VGACON			= (1U <<  2),
+	SYSFB_EVICT_VBE				= (1U <<  3),
+};
+

include/linux/sysfb.h line 34

Quoted 10 lines
include/linux/sysfb.h new file +10 -0
+struct sysfb_evict_ctx {
+	struct apertures_struct *ap;
+	unsigned int flags;
+};
+
+int sysfb_evict_conflicts(struct sysfb_evict_ctx *ctx);
+int sysfb_evict_conflicts_firmware(void);
+int sysfb_evict_conflicts_pci(struct pci_dev *pdev);
+
+#endif /* __LINUX_SYSFB_H */

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#10 lore raw

Re: [PATCH v5 4/7] video: add generic framebuffer eviction

Hi

Quoted 147 lines · Noralf Trønnes

Den 02.09.2016 10:22, skrev David Herrmann:

Quoted 131 lines

There are several situations where we want hardware handover from an early boot GFX driver (e.g., vgacon, vesafb, efifb, simplefb) to a full fletched GFX driver (e.g., most DRM drivers). So far, we relied on remove_conflicting_framebuffers() to do this for us, however, this had a bunch of downsides:

o It only removes conflicting fbdev drivers. It does not drop vgacon, early boot console drivers, conflicting DRM drivers, etc.

o It only unloads the fbdev driver, it does not modify the underlying device or resources. In case of "screen_info" drivers (e.g., efifb) this is fine, since no resources are pinned. However, if the driver binds to a platform-device like "simple-framebuffer", we must make sure to unregister that device as well. Otherwise, pinned resources like IORESOURCE_MEM stay around, triggering WARN_ONs if the following driver requests those resources.

o It is only available if CONFIG_FB is selected.

This commit adds a new infrastructure that manages system-framebuffers (short: sysfb). The initial commit provides conflict-resolution for system-framebuffers. At its core it provides sysfb_evict_conflicts(), which implements conflict detection and removal for all known types of GFX driver hand-overs. So far, this includes platform-device removal, fbdev-firmware-device removal, vgacon removal and VBE detection. To further simplify the callers, it also provides helpers to figure out what hand-over to do, based on the device the new drivers binds to:

o PCI drivers can use sysfb_evict_conflicts_pci(), which will figure
out
the apertures automatically, and does VGA/VBE detection.

o Generic firmware drivers that might be shadowed at any address in memory can use sysfb_evict_conflicts_firmware(), basically removing *all* firmware framebuffers in effect.

This only adds the generic sysfb helpers. No users are converted, yet.

---
  drivers/video/Kconfig  |   4 +
  drivers/video/Makefile |   1 +
  drivers/video/sysfb.c  | 327
+++++++++++++++++++++++++++++++++++++++++++++++++
  include/linux/sysfb.h  |  34 +++++
  4 files changed, 366 insertions(+)

create mode 100644 drivers/video/sysfb.c
create mode 100644 include/linux/sysfb.h

drivers/video/Kconfig +3 -0
index 3c20af9..56a8294 100644
@@ -36,6 +36,10 @@ config VIDEOMODE_HELPERS
  config HDMI
        bool
  +config SYSFB
+       bool
+       select DUMMY_CONSOLE if VT
+
  if VT
        source "drivers/video/console/Kconfig"
  endif
drivers/video/Makefile +1 -0
index 9ad3c17..df7bd75 100644
@@ -1,5 +1,6 @@
  obj-$(CONFIG_VGASTATE)            += vgastate.o
  obj-$(CONFIG_HDMI)                += hdmi.o
+obj-$(CONFIG_SYSFB)              += sysfb.o
    obj-$(CONFIG_VT)              += console/
  obj-$(CONFIG_LOGO)              += logo/
drivers/video/sysfb.c new file +4 -0
new file mode 100644
index 0000000..00585c9
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2013-2016 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify

it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ */

drivers/video/sysfb.c new file +31 -0
+
+#define pr_fmt(fmt) "sysfb: " fmt
+#include <linux/console.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/sysfb.h>
+#include <linux/vt.h>
+
+static bool sysfb_evict_match_resource(struct sysfb_evict_ctx *ctx,
+                                      struct resource *mem)
+{
+       struct aperture *g;
+       unsigned int i;
+
+       for (i = 0; i < ctx->ap->count; ++i) {
+               g = &ctx->ap->ranges[i];
+
+               if (mem->start == g->base)
+                       return true;
+               if (mem->start >= g->base && mem->end < g->base + g->size)
+                       return true;
+               if ((ctx->flags & SYSFB_EVICT_VBE) && mem->start ==

0xA0000)

drivers/video/sysfb.c new file +7 -0
+                       return true;
+       }
+
+       return false;
+}
+
+static int sysfb_evict_platform_device(struct device *dev, void

*userdata)

drivers/video/sysfb.c

Quoted 9 lines
drivers/video/sysfb.c new file +9 -0
+{
+       struct sysfb_evict_ctx *ctx = userdata;
+       struct platform_device *pdev = to_platform_device(dev);
+       struct resource *mem;
+
+       if (!pdev->name)
+               return 0;
+
+       if (!strcmp(pdev->name, "simple-framebuffer")) {

This doesn't work in my case where the device comes from DT and the name also contains the address: pdev->name=1e887000.framebuffer

Quoted 6 lines

This is one way of solving it:

       if (!pdev->dev.driver || !pdev->dev.driver->name)
                return 0;

       if (!strcmp(pdev->dev.driver->name, "simple-framebuffer")) {

Thanks for the hint, but this would skip devices that are not bound. How about the attached hunk?

Thanks
David

drivers/video/sysfb.c +2 -4
index 0f039c6..a4ace3f 100644
@@ -50,10 +50,8 @@ static int sysfb_evict_platform_device
        struct platform_device *pdev = to_platform_device(dev);
        struct resource *mem;
 
-       if (!pdev->name)
-               return 0;
-
-       if (!strcmp(pdev->name, "simple-framebuffer")) {
+       if ((pdev->name && !strcmp(pdev->name, "simple-framebuffer")) ||
+           of_device_is_compatible(pdev->dev.of_node, "simple-framebuffer")) {
                mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
                if (!mem)
                        return 0;

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#11 lore raw

Re: [PATCH v5 4/7] video: add generic framebuffer eviction

Den 05.09.2016 13:19, skrev David Herrmann:

Quoted 167 lines

Hi

Quoted 144 lines · Noralf Trønnes

Den 02.09.2016 10:22, skrev David Herrmann:

Quoted 130 lines

There are several situations where we want hardware handover from an early boot GFX driver (e.g., vgacon, vesafb, efifb, simplefb) to a full fletched GFX driver (e.g., most DRM drivers). So far, we relied on remove_conflicting_framebuffers() to do this for us, however, this had a bunch of downsides:

o It only removes conflicting fbdev drivers. It does not drop vgacon, early boot console drivers, conflicting DRM drivers, etc.

o It only unloads the fbdev driver, it does not modify the underlying device or resources. In case of "screen_info" drivers (e.g., efifb) this is fine, since no resources are pinned. However, if the driver binds to a platform-device like "simple-framebuffer", we must make sure to unregister that device as well. Otherwise, pinned resources like IORESOURCE_MEM stay around, triggering WARN_ONs if the following driver requests those resources.

o It is only available if CONFIG_FB is selected.

This commit adds a new infrastructure that manages system-framebuffers (short: sysfb). The initial commit provides conflict-resolution for system-framebuffers. At its core it provides sysfb_evict_conflicts(), which implements conflict detection and removal for all known types of GFX driver hand-overs. So far, this includes platform-device removal, fbdev-firmware-device removal, vgacon removal and VBE detection. To further simplify the callers, it also provides helpers to figure out what hand-over to do, based on the device the new drivers binds to:

o PCI drivers can use sysfb_evict_conflicts_pci(), which will figure
out
the apertures automatically, and does VGA/VBE detection.

o Generic firmware drivers that might be shadowed at any address in memory can use sysfb_evict_conflicts_firmware(), basically removing *all* firmware framebuffers in effect.

This only adds the generic sysfb helpers. No users are converted, yet.

---
   drivers/video/Kconfig  |   4 +
   drivers/video/Makefile |   1 +
   drivers/video/sysfb.c  | 327
+++++++++++++++++++++++++++++++++++++++++++++++++
   include/linux/sysfb.h  |  34 +++++
   4 files changed, 366 insertions(+)

create mode 100644 drivers/video/sysfb.c
create mode 100644 include/linux/sysfb.h

drivers/video/Kconfig +3 -0
index 3c20af9..56a8294 100644
@@ -36,6 +36,10 @@ config VIDEOMODE_HELPERS
   config HDMI
         bool
   +config SYSFB
+       bool
+       select DUMMY_CONSOLE if VT
+
   if VT
         source "drivers/video/console/Kconfig"
   endif
drivers/video/Makefile +1 -0
index 9ad3c17..df7bd75 100644
@@ -1,5 +1,6 @@
   obj-$(CONFIG_VGASTATE)            += vgastate.o
   obj-$(CONFIG_HDMI)                += hdmi.o
+obj-$(CONFIG_SYSFB)              += sysfb.o
     obj-$(CONFIG_VT)              += console/
   obj-$(CONFIG_LOGO)              += logo/
drivers/video/sysfb.c new file +4 -0
new file mode 100644
index 0000000..00585c9
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2013-2016 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify

it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ */

drivers/video/sysfb.c new file +31 -0
+
+#define pr_fmt(fmt) "sysfb: " fmt
+#include <linux/console.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/fb.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/sysfb.h>
+#include <linux/vt.h>
+
+static bool sysfb_evict_match_resource(struct sysfb_evict_ctx *ctx,
+                                      struct resource *mem)
+{
+       struct aperture *g;
+       unsigned int i;
+
+       for (i = 0; i < ctx->ap->count; ++i) {
+               g = &ctx->ap->ranges[i];
+
+               if (mem->start == g->base)
+                       return true;
+               if (mem->start >= g->base && mem->end < g->base + g->size)
+                       return true;
+               if ((ctx->flags & SYSFB_EVICT_VBE) && mem->start ==

0xA0000)

drivers/video/sysfb.c new file +7 -0
+                       return true;
+       }
+
+       return false;
+}
+
+static int sysfb_evict_platform_device(struct device *dev, void

*userdata)

drivers/video/sysfb.c

Quoted 9 lines
drivers/video/sysfb.c new file +9 -0
+{
+       struct sysfb_evict_ctx *ctx = userdata;
+       struct platform_device *pdev = to_platform_device(dev);
+       struct resource *mem;
+
+       if (!pdev->name)
+               return 0;
+
+       if (!strcmp(pdev->name, "simple-framebuffer")) {

This doesn't work in my case where the device comes from DT and the name also contains the address: pdev->name=1e887000.framebuffer

Quoted 6 lines

This is one way of solving it:

        if (!pdev->dev.driver || !pdev->dev.driver->name)
                 return 0;

        if (!strcmp(pdev->dev.driver->name, "simple-framebuffer")) {

Thanks for the hint, but this would skip devices that are not bound. How about the attached hunk?

Thanks
David

drivers/video/sysfb.c +0 -0
index 0f039c6..a4ace3f 100644
@@ -50,10 +50,8 @@ static int sysfb_evict_platform_device
         struct platform_device *pdev = to_platform_device(dev);
         struct resource *mem;

drivers/video/sysfb.c static int sysfb_evict_platform_device · line 57

Quoted 10 lines
drivers/video/sysfb.c +2 -4
 
-       if (!pdev->name)
-               return 0;
-
-       if (!strcmp(pdev->name, "simple-framebuffer")) {
+       if ((pdev->name && !strcmp(pdev->name, "simple-framebuffer")) ||
+           of_device_is_compatible(pdev->dev.of_node, "simple-framebuffer")) {
                 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
                 if (!mem)
                         return 0;

This worked fine.

Noralf.

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#12 lore raw

PATCH v5 5/7 drm: switch to sysfb_evict_conflicts()

In reply to David Herrmann

Switch over all DRM drivers to use the new sysfb_evict_conflicts() infrastructure. The only non-trivial conversion is i915, since it does not make use of the generic PCI resources, but assembles the apertures via intel ggtt queries.

---
 drivers/gpu/drm/Kconfig                  |  1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c  | 24 +----------
 drivers/gpu/drm/bochs/bochs_drv.c        | 19 +--------
 drivers/gpu/drm/i915/i915_drv.c          | 73 ++++++--------------------------
 drivers/gpu/drm/mgag200/mgag200_drv.c    | 27 +++---------
 drivers/gpu/drm/mgag200/mgag200_main.c   |  9 ----
 drivers/gpu/drm/nouveau/nouveau_drm.c    | 33 +++------------
 drivers/gpu/drm/radeon/radeon_drv.c      | 24 +----------
 drivers/gpu/drm/sun4i/sun4i_drv.c        | 24 +++--------
 drivers/gpu/drm/vc4/vc4_drv.c            | 25 +++--------
 drivers/gpu/drm/virtio/virtgpu_drm_bus.c | 24 +----------
 11 files changed, 44 insertions(+), 239 deletions(-)
drivers/gpu/drm/Kconfig +1 -0
index fc35731..f27f9b5 100644
@@ -12,6 +12,7 @@ menuconfig DRM
 	select I2C
 	select I2C_ALGOBIT
 	select DMA_SHARED_BUFFER
+	select SYSFB
 	help
 	  Kernel-level support for the Direct Rendering Infrastructure (DRI)
 	  introduced in XFree86 4.0. If you say Y here, you need to select
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +2 -22
index 9aa533c..a1e67da 100644
@@ -38,6 +38,7 @@
 #include <linux/console.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
+#include <linux/sysfb.h>
 #include <linux/vga_switcheroo.h>
 #include "drm_crtc_helper.h"
 
@@ -326,27 +327,6 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
 
 static struct drm_driver kms_driver;
 
-static int amdgpu_kick_out_firmware_fb(struct pci_dev *pdev)
-{
-	struct apertures_struct *ap;
-	bool primary = false;
-
-	ap = alloc_apertures(1);
-	if (!ap)
-		return -ENOMEM;
-
-	ap->ranges[0].base = pci_resource_start(pdev, 0);
-	ap->ranges[0].size = pci_resource_len(pdev, 0);
-
-#ifdef CONFIG_X86
-	primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
-#endif
-	remove_conflicting_framebuffers(ap, "amdgpudrmfb", primary);
-	kfree(ap);
-
-	return 0;
-}
-
 static int amdgpu_pci_probe(struct pci_dev *pdev,
 			    const struct pci_device_id *ent)
 {
@@ -368,7 +348,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
 		return ret;
 
 	/* Get rid of things like offb */
-	ret = amdgpu_kick_out_firmware_fb(pdev);
+	ret = sysfb_evict_conflicts_pci(pdev);
 	if (ret)
 		return ret;
 
drivers/gpu/drm/bochs/bochs_drv.c +2 -17
index abace82..99c4ea3 100644
@@ -8,6 +8,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/sysfb.h>
 
 #include "bochs.h"
 
@@ -143,28 +144,12 @@ static const struct dev_pm_ops bochs_pm_ops = {
 /* ---------------------------------------------------------------------- */
 /* pci interface                                                          */
 
-static int bochs_kick_out_firmware_fb(struct pci_dev *pdev)
-{
-	struct apertures_struct *ap;
-
-	ap = alloc_apertures(1);
-	if (!ap)
-		return -ENOMEM;
-
-	ap->ranges[0].base = pci_resource_start(pdev, 0);
-	ap->ranges[0].size = pci_resource_len(pdev, 0);
-	remove_conflicting_framebuffers(ap, "bochsdrmfb", false);
-	kfree(ap);
-
-	return 0;
-}
-
 static int bochs_pci_probe(struct pci_dev *pdev,
 			   const struct pci_device_id *ent)
 {
 	int ret;
 
-	ret = bochs_kick_out_firmware_fb(pdev);
+	ret = sysfb_evict_conflicts_pci(pdev);
 	if (ret)
 		return ret;
 
drivers/gpu/drm/i915/i915_drv.c +14 -59

110 lines not on this page · raw message

drivers/gpu/drm/mgag200/mgag200_drv.c +6 -21
index 2b4b125..f30105b 100644
@@ -10,6 +10,7 @@
  */
 #include <linux/module.h>
 #include <linux/console.h>
+#include <linux/sysfb.h>
 #include <drm/drmP.h>
 
 #include "mgag200_drv.h"
@@ -41,29 +42,13 @@ static const struct pci_device_id pciidlist[] = {
 
 MODULE_DEVICE_TABLE(pci, pciidlist);
 
-static void mgag200_kick_out_firmware_fb(struct pci_dev *pdev)
-{
-	struct apertures_struct *ap;
-	bool primary = false;
-
-	ap = alloc_apertures(1);
-	if (!ap)
-		return;
-
-	ap->ranges[0].base = pci_resource_start(pdev, 0);
-	ap->ranges[0].size = pci_resource_len(pdev, 0);
-
-#ifdef CONFIG_X86
-	primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
-#endif
-	remove_conflicting_framebuffers(ap, "mgag200drmfb", primary);
-	kfree(ap);
-}
-
-
 static int mga_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	mgag200_kick_out_firmware_fb(pdev);
+	int ret;
+
+	ret = sysfb_evict_conflicts_pci(pdev);
+	if (ret < 0)
+		return ret;
 
 	return drm_get_pci_dev(pdev, ent, &driver);
 }
drivers/gpu/drm/mgag200/mgag200_main.c +0 -9
index 13798b3..4723407 100644
@@ -124,20 +124,11 @@ static int mga_probe_vram(struct mga_device *mdev, void __iomem *mem)
 static int mga_vram_init(struct mga_device *mdev)
 {
 	void __iomem *mem;
-	struct apertures_struct *aper = alloc_apertures(1);
-	if (!aper)
-		return -ENOMEM;
 
 	/* BAR 0 is VRAM */
 	mdev->mc.vram_base = pci_resource_start(mdev->dev->pdev, 0);
 	mdev->mc.vram_window = pci_resource_len(mdev->dev->pdev, 0);
 
-	aper->ranges[0].base = mdev->mc.vram_base;
-	aper->ranges[0].size = mdev->mc.vram_window;
-
-	remove_conflicting_framebuffers(aper, "mgafb", true);
-	kfree(aper);
-
 	if (!devm_request_mem_region(mdev->dev->dev, mdev->mc.vram_base, mdev->mc.vram_window,
 				"mgadrmfb_vram")) {
 		DRM_ERROR("can't reserve VRAM\n");
drivers/gpu/drm/nouveau/nouveau_drm.c +5 -28
index 66c1280..193e833 100644
@@ -27,6 +27,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/pm_runtime.h>
+#include <linux/sysfb.h>
 #include <linux/vga_switcheroo.h>
 
 #include "drmP.h"
@@ -310,8 +311,6 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
 			     const struct pci_device_id *pent)
 {
 	struct nvkm_device *device;
-	struct apertures_struct *aper;
-	bool boot = false;
 	int ret;
 
 	if (vga_switcheroo_client_probe_defer(pdev))
@@ -326,34 +325,12 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
 
 	nvkm_device_del(&device);
 
-	/* Remove conflicting drivers (vesafb, efifb etc). */
-	aper = alloc_apertures(3);
-	if (!aper)
-		return -ENOMEM;
-
-	aper->ranges[0].base = pci_resource_start(pdev, 1);
-	aper->ranges[0].size = pci_resource_len(pdev, 1);
-	aper->count = 1;
-
-	if (pci_resource_len(pdev, 2)) {
-		aper->ranges[aper->count].base = pci_resource_start(pdev, 2);
-		aper->ranges[aper->count].size = pci_resource_len(pdev, 2);
-		aper->count++;
-	}
-
-	if (pci_resource_len(pdev, 3)) {
-		aper->ranges[aper->count].base = pci_resource_start(pdev, 3);
-		aper->ranges[aper->count].size = pci_resource_len(pdev, 3);
-		aper->count++;
+	if (nouveau_modeset != 2) {
+		ret = sysfb_evict_conflicts_pci(pdev);
+		if (ret < 0)
+			return ret;
 	}
 
-#ifdef CONFIG_X86
-	boot = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
-#endif
-	if (nouveau_modeset != 2)
-		remove_conflicting_framebuffers(aper, "nouveaufb", boot);
-	kfree(aper);
-
 	ret = nvkm_device_pci_new(pdev, nouveau_config, nouveau_debug,
 				  true, true, ~0ULL, &device);
 	if (ret)
drivers/gpu/drm/radeon/radeon_drv.c +2 -22
index c01a7c6..a0c11bd 100644
@@ -37,6 +37,7 @@
 #include <linux/console.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
+#include <linux/sysfb.h>
 #include <linux/vga_switcheroo.h>
 #include <drm/drm_gem.h>
 
@@ -309,27 +310,6 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
 
 static struct drm_driver kms_driver;
 
-static int radeon_kick_out_firmware_fb(struct pci_dev *pdev)
-{
-	struct apertures_struct *ap;
-	bool primary = false;
-
-	ap = alloc_apertures(1);
-	if (!ap)
-		return -ENOMEM;
-
-	ap->ranges[0].base = pci_resource_start(pdev, 0);
-	ap->ranges[0].size = pci_resource_len(pdev, 0);
-
-#ifdef CONFIG_X86
-	primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
-#endif
-	remove_conflicting_framebuffers(ap, "radeondrmfb", primary);
-	kfree(ap);
-
-	return 0;
-}
-
 static int radeon_pci_probe(struct pci_dev *pdev,
 			    const struct pci_device_id *ent)
 {
@@ -347,7 +327,7 @@ static int radeon_pci_probe(struct pci_dev *pdev,
 		return -EPROBE_DEFER;
 
 	/* Get rid of things like offb */
-	ret = radeon_kick_out_firmware_fb(pdev);
+	ret = sysfb_evict_conflicts_pci(pdev);
 	if (ret)
 		return ret;
 
drivers/gpu/drm/sun4i/sun4i_drv.c +5 -19
index 7092daa..ac388b5 100644
@@ -12,6 +12,7 @@
 
 #include <linux/component.h>
 #include <linux/of_graph.h>
+#include <linux/sysfb.h>
 
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
@@ -97,28 +98,16 @@ static struct drm_driver sun4i_drv_driver = {
 	.disable_vblank		= sun4i_drv_disable_vblank,
 };
 
-static void sun4i_remove_framebuffers(void)
-{
-	struct apertures_struct *ap;
-
-	ap = alloc_apertures(1);
-	if (!ap)
-		return;
-
-	/* The framebuffer can be located anywhere in RAM */
-	ap->ranges[0].base = 0;
-	ap->ranges[0].size = ~0;
-
-	remove_conflicting_framebuffers(ap, "sun4i-drm-fb", false);
-	kfree(ap);
-}
-
 static int sun4i_drv_bind(struct device *dev)
 {
 	struct drm_device *drm;
 	struct sun4i_drv *drv;
 	int ret;
 
+	ret = sysfb_evict_conflicts_firmware();
+	if (ret < 0)
+		return ret;
+
 	drm = drm_dev_alloc(&sun4i_drv_driver, dev);
 	if (!drm)
 		return -ENOMEM;
@@ -156,9 +145,6 @@ static int sun4i_drv_bind(struct device *dev)
 	}
 	drm->irq_enabled = true;
 
-	/* Remove early framebuffers (ie. simplefb) */
-	sun4i_remove_framebuffers();
-
 	/* Create our framebuffer */
 	drv->fbdev = sun4i_framebuffer_init(drm);
 	if (IS_ERR(drv->fbdev)) {
drivers/gpu/drm/vc4/vc4_drv.c +5 -20
index 8b42d31..679e65a 100644
@@ -15,6 +15,7 @@
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/sysfb.h>
 #include "drm_fb_cma_helper.h"
 
 #include "uapi/drm/vc4_drm.h"
@@ -200,24 +201,6 @@ static void vc4_match_add_drivers(struct device *dev,
 	}
 }
 
-static void vc4_kick_out_firmware_fb(void)
-{
-	struct apertures_struct *ap;
-
-	ap = alloc_apertures(1);
-	if (!ap)
-		return;
-
-	/* Since VC4 is a UMA device, the simplefb node may have been
-	 * located anywhere in memory.
-	 */
-	ap->ranges[0].base = 0;
-	ap->ranges[0].size = ~0;
-
-	remove_conflicting_framebuffers(ap, "vc4drmfb", false);
-	kfree(ap);
-}
-
 static int vc4_drm_bind(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
@@ -225,6 +208,10 @@ static int vc4_drm_bind(struct device *dev)
 	struct vc4_dev *vc4;
 	int ret = 0;
 
+	ret = sysfb_evict_conflicts_firmware();
+	if (ret < 0)
+		return ret;
+
 	dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
 	vc4 = devm_kzalloc(dev, sizeof(*vc4), GFP_KERNEL);
@@ -248,8 +235,6 @@ static int vc4_drm_bind(struct device *dev)
 	if (ret)
 		goto gem_destroy;
 
-	vc4_kick_out_firmware_fb();
-
 	ret = drm_dev_register(drm, 0);
 	if (ret < 0)
 		goto unbind_all;
drivers/gpu/drm/virtio/virtgpu_drm_bus.c +2 -22
index 7f0e93f87..d6a8a94 100644
@@ -24,29 +24,10 @@
  */
 
 #include <linux/pci.h>
+#include <linux/sysfb.h>
 
 #include "virtgpu_drv.h"
 
-static void virtio_pci_kick_out_firmware_fb(struct pci_dev *pci_dev)
-{
-	struct apertures_struct *ap;
-	bool primary;
-
-	ap = alloc_apertures(1);
-	if (!ap)
-		return;
-
-	ap->ranges[0].base = pci_resource_start(pci_dev, 0);
-	ap->ranges[0].size = pci_resource_len(pci_dev, 0);
-
-	primary = pci_dev->resource[PCI_ROM_RESOURCE].flags
-		& IORESOURCE_ROM_SHADOW;
-
-	remove_conflicting_framebuffers(ap, "virtiodrmfb", primary);
-
-	kfree(ap);
-}
-
 int drm_virtio_init(struct drm_driver *driver, struct virtio_device *vdev)
 {
 	struct drm_device *dev;
@@ -65,8 +46,7 @@ int drm_virtio_init(struct drm_driver *driver, struct virtio_device *vdev)
 		DRM_INFO("pci: %s detected\n",
 			 vga ? "virtio-vga" : "virtio-gpu-pci");
 		dev->pdev = pdev;
-		if (vga)
-			virtio_pci_kick_out_firmware_fb(pdev);
+		sysfb_evict_conflicts_pci(pdev);
 	}
 
 	ret = drm_dev_register(dev, 0);
Signature · 6 lines
2.9.3

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
#13 lore raw

Re: [PATCH v5 5/7] drm: switch to sysfb_evict_conflicts()

Den 02.09.2016 10:22, skrev David Herrmann:

Quoted 7 lines

Switch over all DRM drivers to use the new sysfb_evict_conflicts() infrastructure. The only non-trivial conversion is i915, since it does not make use of the generic PCI resources, but assembles the apertures via intel ggtt queries.

---

This doesn't apply now with Daniel's wrapper added:
drm_fb_helper_remove_conflicting_framebuffers().

Noralf.

Quoted 562 lines
  drivers/gpu/drm/Kconfig                  |  1 +
  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c  | 24 +----------
  drivers/gpu/drm/bochs/bochs_drv.c        | 19 +--------
  drivers/gpu/drm/i915/i915_drv.c          | 73 ++++++--------------------------
  drivers/gpu/drm/mgag200/mgag200_drv.c    | 27 +++---------
  drivers/gpu/drm/mgag200/mgag200_main.c   |  9 ----
  drivers/gpu/drm/nouveau/nouveau_drm.c    | 33 +++------------
  drivers/gpu/drm/radeon/radeon_drv.c      | 24 +----------
  drivers/gpu/drm/sun4i/sun4i_drv.c        | 24 +++--------
  drivers/gpu/drm/vc4/vc4_drv.c            | 25 +++--------
  drivers/gpu/drm/virtio/virtgpu_drm_bus.c | 24 +----------
  11 files changed, 44 insertions(+), 239 deletions(-)
drivers/gpu/drm/Kconfig +1 -0
index fc35731..f27f9b5 100644
@@ -12,6 +12,7 @@ menuconfig DRM
  	select I2C
  	select I2C_ALGOBIT
  	select DMA_SHARED_BUFFER
+	select SYSFB
  	help
  	  Kernel-level support for the Direct Rendering Infrastructure (DRI)
  	  introduced in XFree86 4.0. If you say Y here, you need to select
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +2 -22
index 9aa533c..a1e67da 100644
@@ -38,6 +38,7 @@
  #include <linux/console.h>
  #include <linux/module.h>
  #include <linux/pm_runtime.h>
+#include <linux/sysfb.h>
  #include <linux/vga_switcheroo.h>
  #include "drm_crtc_helper.h"
 
@@ -326,27 +327,6 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
 
  static struct drm_driver kms_driver;
 
-static int amdgpu_kick_out_firmware_fb(struct pci_dev *pdev)
-{
-	struct apertures_struct *ap;
-	bool primary = false;
-
-	ap = alloc_apertures(1);
-	if (!ap)
-		return -ENOMEM;
-
-	ap->ranges[0].base = pci_resource_start(pdev, 0);
-	ap->ranges[0].size = pci_resource_len(pdev, 0);
-
-#ifdef CONFIG_X86
-	primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
-#endif
-	remove_conflicting_framebuffers(ap, "amdgpudrmfb", primary);
-	kfree(ap);
-
-	return 0;
-}
-
  static int amdgpu_pci_probe(struct pci_dev *pdev,
  			    const struct pci_device_id *ent)
  {
@@ -368,7 +348,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
  		return ret;
 
  	/* Get rid of things like offb */
-	ret = amdgpu_kick_out_firmware_fb(pdev);
+	ret = sysfb_evict_conflicts_pci(pdev);
  	if (ret)
  		return ret;
 
drivers/gpu/drm/bochs/bochs_drv.c +2 -17
index abace82..99c4ea3 100644
@@ -8,6 +8,7 @@
  #include <linux/mm.h>
  #include <linux/module.h>
  #include <linux/slab.h>
+#include <linux/sysfb.h>
 
  #include "bochs.h"
 
@@ -143,28 +144,12 @@ static const struct dev_pm_ops bochs_pm_ops = {
  /* ---------------------------------------------------------------------- */
  /* pci interface                                                          */
 
-static int bochs_kick_out_firmware_fb(struct pci_dev *pdev)
-{
-	struct apertures_struct *ap;
-
-	ap = alloc_apertures(1);
-	if (!ap)
-		return -ENOMEM;
-
-	ap->ranges[0].base = pci_resource_start(pdev, 0);
-	ap->ranges[0].size = pci_resource_len(pdev, 0);
-	remove_conflicting_framebuffers(ap, "bochsdrmfb", false);
-	kfree(ap);
-
-	return 0;
-}
-
  static int bochs_pci_probe(struct pci_dev *pdev,
  			   const struct pci_device_id *ent)
  {
  	int ret;
 
-	ret = bochs_kick_out_firmware_fb(pdev);
+	ret = sysfb_evict_conflicts_pci(pdev);
  	if (ret)
  		return ret;
 
drivers/gpu/drm/i915/i915_drv.c +14 -59
index 95ddd56..4d6a65dd 100644
@@ -36,6 +36,7 @@
  #include <linux/pm_runtime.h>
  #include <linux/pnp.h>
  #include <linux/slab.h>
+#include <linux/sysfb.h>
  #include <linux/vgaarb.h>
  #include <linux/vga_switcheroo.h>
  #include <linux/vt.h>
@@ -687,70 +688,32 @@ out:
  	return ret;
  }
 
-#if IS_ENABLED(CONFIG_FB)
  static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
  {
-	struct apertures_struct *ap;
+	struct sysfb_evict_ctx ctx = {};
  	struct pci_dev *pdev = dev_priv->drm.pdev;
  	struct i915_ggtt *ggtt = &dev_priv->ggtt;
-	bool primary;
  	int ret;
 
-	ap = alloc_apertures(1);
-	if (!ap)
-		return -ENOMEM;
-
-	ap->ranges[0].base = ggtt->mappable_base;
-	ap->ranges[0].size = ggtt->mappable_end;
-
-	primary =
-		pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
-
-	ret = remove_conflicting_framebuffers(ap, "inteldrmfb", primary);
-
-	kfree(ap);
-
-	return ret;
-}
-#else
-static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
-{
-	return 0;
-}
-#endif
+	ctx.flags = SYSFB_EVICT_PLATFORM |
+		    SYSFB_EVICT_FBDEV |
+		    SYSFB_EVICT_VGACON;
 
-#if !defined(CONFIG_VGA_CONSOLE)
-static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
-{
-	return 0;
-}
-#elif !defined(CONFIG_DUMMY_CONSOLE)
-static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
-{
-	return -ENODEV;
-}
-#else
-static int i915_kick_out_vgacon(struct drm_i915_private *dev_priv)
-{
-	int ret = 0;
+	ctx.ap = alloc_apertures(1);
+	if (!ctx.ap)
+		return -ENOMEM;
 
-	DRM_INFO("Replacing VGA console driver\n");
+	ctx.ap->ranges[0].base = ggtt->mappable_base;
+	ctx.ap->ranges[0].size = ggtt->mappable_end;
 
-	console_lock();
-	if (con_is_bound(&vga_con))
-		ret = do_take_over_console(&dummy_con, 0, MAX_NR_CONSOLES - 1, 1);
-	if (ret == 0) {
-		ret = do_unregister_con_driver(&vga_con);
+	if (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)
+		ctx.flags |= SYSFB_EVICT_VBE;
 
-		/* Ignore "already unregistered". */
-		if (ret == -ENODEV)
-			ret = 0;
-	}
-	console_unlock();
+	ret = sysfb_evict_conflicts(&ctx);
 
+	kfree(ctx.ap);
  	return ret;
  }
-#endif
 
  static void intel_init_dpio(struct drm_i915_private *dev_priv)
  {
@@ -1032,20 +995,12 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
  		goto out_ggtt;
  	}
 
-	/* WARNING: Apparently we must kick fbdev drivers before vgacon,
-	 * otherwise the vga fbdev driver falls over. */
  	ret = i915_kick_out_firmware_fb(dev_priv);
  	if (ret) {
  		DRM_ERROR("failed to remove conflicting framebuffer drivers\n");
  		goto out_ggtt;
  	}
 
-	ret = i915_kick_out_vgacon(dev_priv);
-	if (ret) {
-		DRM_ERROR("failed to remove conflicting VGA console\n");
-		goto out_ggtt;
-	}
-
  	pci_set_master(dev->pdev);
 
  	/* overlay on gen2 is broken and can't address above 1G */
drivers/gpu/drm/mgag200/mgag200_drv.c +6 -21
index 2b4b125..f30105b 100644
@@ -10,6 +10,7 @@
   */
  #include <linux/module.h>
  #include <linux/console.h>
+#include <linux/sysfb.h>
  #include <drm/drmP.h>
 
  #include "mgag200_drv.h"
@@ -41,29 +42,13 @@ static const struct pci_device_id pciidlist[] = {
 
  MODULE_DEVICE_TABLE(pci, pciidlist);
 
-static void mgag200_kick_out_firmware_fb(struct pci_dev *pdev)
-{
-	struct apertures_struct *ap;
-	bool primary = false;
-
-	ap = alloc_apertures(1);
-	if (!ap)
-		return;
-
-	ap->ranges[0].base = pci_resource_start(pdev, 0);
-	ap->ranges[0].size = pci_resource_len(pdev, 0);
-
-#ifdef CONFIG_X86
-	primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
-#endif
-	remove_conflicting_framebuffers(ap, "mgag200drmfb", primary);
-	kfree(ap);
-}
-
-
  static int mga_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
  {
-	mgag200_kick_out_firmware_fb(pdev);
+	int ret;
+
+	ret = sysfb_evict_conflicts_pci(pdev);
+	if (ret < 0)
+		return ret;
 
  	return drm_get_pci_dev(pdev, ent, &driver);
  }
drivers/gpu/drm/mgag200/mgag200_main.c +0 -9
index 13798b3..4723407 100644
@@ -124,20 +124,11 @@ static int mga_probe_vram(struct mga_device *mdev, void __iomem *mem)
  static int mga_vram_init(struct mga_device *mdev)
  {
  	void __iomem *mem;
-	struct apertures_struct *aper = alloc_apertures(1);
-	if (!aper)
-		return -ENOMEM;
 
  	/* BAR 0 is VRAM */
  	mdev->mc.vram_base = pci_resource_start(mdev->dev->pdev, 0);
  	mdev->mc.vram_window = pci_resource_len(mdev->dev->pdev, 0);
 
-	aper->ranges[0].base = mdev->mc.vram_base;
-	aper->ranges[0].size = mdev->mc.vram_window;
-
-	remove_conflicting_framebuffers(aper, "mgafb", true);
-	kfree(aper);
-
  	if (!devm_request_mem_region(mdev->dev->dev, mdev->mc.vram_base, mdev->mc.vram_window,
  				"mgadrmfb_vram")) {
  		DRM_ERROR("can't reserve VRAM\n");
drivers/gpu/drm/nouveau/nouveau_drm.c +5 -28
index 66c1280..193e833 100644
@@ -27,6 +27,7 @@
  #include <linux/module.h>
  #include <linux/pci.h>
  #include <linux/pm_runtime.h>
+#include <linux/sysfb.h>
  #include <linux/vga_switcheroo.h>
 
  #include "drmP.h"
@@ -310,8 +311,6 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
  			     const struct pci_device_id *pent)
  {
  	struct nvkm_device *device;
-	struct apertures_struct *aper;
-	bool boot = false;
  	int ret;
 
  	if (vga_switcheroo_client_probe_defer(pdev))
@@ -326,34 +325,12 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
 
  	nvkm_device_del(&device);
 
-	/* Remove conflicting drivers (vesafb, efifb etc). */
-	aper = alloc_apertures(3);
-	if (!aper)
-		return -ENOMEM;
-
-	aper->ranges[0].base = pci_resource_start(pdev, 1);
-	aper->ranges[0].size = pci_resource_len(pdev, 1);
-	aper->count = 1;
-
-	if (pci_resource_len(pdev, 2)) {
-		aper->ranges[aper->count].base = pci_resource_start(pdev, 2);
-		aper->ranges[aper->count].size = pci_resource_len(pdev, 2);
-		aper->count++;
-	}
-
-	if (pci_resource_len(pdev, 3)) {
-		aper->ranges[aper->count].base = pci_resource_start(pdev, 3);
-		aper->ranges[aper->count].size = pci_resource_len(pdev, 3);
-		aper->count++;
+	if (nouveau_modeset != 2) {
+		ret = sysfb_evict_conflicts_pci(pdev);
+		if (ret < 0)
+			return ret;
  	}
 
-#ifdef CONFIG_X86
-	boot = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
-#endif
-	if (nouveau_modeset != 2)
-		remove_conflicting_framebuffers(aper, "nouveaufb", boot);
-	kfree(aper);
-
  	ret = nvkm_device_pci_new(pdev, nouveau_config, nouveau_debug,
  				  true, true, ~0ULL, &device);
  	if (ret)
drivers/gpu/drm/radeon/radeon_drv.c +2 -22
index c01a7c6..a0c11bd 100644
@@ -37,6 +37,7 @@
  #include <linux/console.h>
  #include <linux/module.h>
  #include <linux/pm_runtime.h>
+#include <linux/sysfb.h>
  #include <linux/vga_switcheroo.h>
  #include <drm/drm_gem.h>
 
@@ -309,27 +310,6 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
 
  static struct drm_driver kms_driver;
 
-static int radeon_kick_out_firmware_fb(struct pci_dev *pdev)
-{
-	struct apertures_struct *ap;
-	bool primary = false;
-
-	ap = alloc_apertures(1);
-	if (!ap)
-		return -ENOMEM;
-
-	ap->ranges[0].base = pci_resource_start(pdev, 0);
-	ap->ranges[0].size = pci_resource_len(pdev, 0);
-
-#ifdef CONFIG_X86
-	primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
-#endif
-	remove_conflicting_framebuffers(ap, "radeondrmfb", primary);
-	kfree(ap);
-
-	return 0;
-}
-
  static int radeon_pci_probe(struct pci_dev *pdev,
  			    const struct pci_device_id *ent)
  {
@@ -347,7 +327,7 @@ static int radeon_pci_probe(struct pci_dev *pdev,
  		return -EPROBE_DEFER;
 
  	/* Get rid of things like offb */
-	ret = radeon_kick_out_firmware_fb(pdev);
+	ret = sysfb_evict_conflicts_pci(pdev);
  	if (ret)
  		return ret;
 
drivers/gpu/drm/sun4i/sun4i_drv.c +5 -19
index 7092daa..ac388b5 100644
@@ -12,6 +12,7 @@
 
  #include <linux/component.h>
  #include <linux/of_graph.h>
+#include <linux/sysfb.h>
 
  #include <drm/drmP.h>
  #include <drm/drm_crtc_helper.h>
@@ -97,28 +98,16 @@ static struct drm_driver sun4i_drv_driver = {
  	.disable_vblank		= sun4i_drv_disable_vblank,
  };
 
-static void sun4i_remove_framebuffers(void)
-{
-	struct apertures_struct *ap;
-
-	ap = alloc_apertures(1);
-	if (!ap)
-		return;
-
-	/* The framebuffer can be located anywhere in RAM */
-	ap->ranges[0].base = 0;
-	ap->ranges[0].size = ~0;
-
-	remove_conflicting_framebuffers(ap, "sun4i-drm-fb", false);
-	kfree(ap);
-}
-
  static int sun4i_drv_bind(struct device *dev)
  {
  	struct drm_device *drm;
  	struct sun4i_drv *drv;
  	int ret;
 
+	ret = sysfb_evict_conflicts_firmware();
+	if (ret < 0)
+		return ret;
+
  	drm = drm_dev_alloc(&sun4i_drv_driver, dev);
  	if (!drm)
  		return -ENOMEM;
@@ -156,9 +145,6 @@ static int sun4i_drv_bind(struct device *dev)
  	}
  	drm->irq_enabled = true;
 
-	/* Remove early framebuffers (ie. simplefb) */
-	sun4i_remove_framebuffers();
-
  	/* Create our framebuffer */
  	drv->fbdev = sun4i_framebuffer_init(drm);
  	if (IS_ERR(drv->fbdev)) {
drivers/gpu/drm/vc4/vc4_drv.c +5 -20
index 8b42d31..679e65a 100644
@@ -15,6 +15,7 @@
  #include <linux/of_platform.h>
  #include <linux/platform_device.h>
  #include <linux/pm_runtime.h>
+#include <linux/sysfb.h>
  #include "drm_fb_cma_helper.h"
 
  #include "uapi/drm/vc4_drm.h"
@@ -200,24 +201,6 @@ static void vc4_match_add_drivers(struct device *dev,
  	}
  }
 
-static void vc4_kick_out_firmware_fb(void)
-{
-	struct apertures_struct *ap;
-
-	ap = alloc_apertures(1);
-	if (!ap)
-		return;
-
-	/* Since VC4 is a UMA device, the simplefb node may have been
-	 * located anywhere in memory.
-	 */
-	ap->ranges[0].base = 0;
-	ap->ranges[0].size = ~0;
-
-	remove_conflicting_framebuffers(ap, "vc4drmfb", false);
-	kfree(ap);
-}
-
  static int vc4_drm_bind(struct device *dev)
  {
  	struct platform_device *pdev = to_platform_device(dev);
@@ -225,6 +208,10 @@ static int vc4_drm_bind(struct device *dev)
  	struct vc4_dev *vc4;
  	int ret = 0;
 
+	ret = sysfb_evict_conflicts_firmware();
+	if (ret < 0)
+		return ret;
+
  	dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
  	vc4 = devm_kzalloc(dev, sizeof(*vc4), GFP_KERNEL);
@@ -248,8 +235,6 @@ static int vc4_drm_bind(struct device *dev)
  	if (ret)
  		goto gem_destroy;
 
-	vc4_kick_out_firmware_fb();
-
  	ret = drm_dev_register(drm, 0);
  	if (ret < 0)
  		goto unbind_all;
drivers/gpu/drm/virtio/virtgpu_drm_bus.c +1 -20
index 7f0e93f87..d6a8a94 100644
@@ -24,29 +24,10 @@
   */
 
  #include <linux/pci.h>
+#include <linux/sysfb.h>
 
  #include "virtgpu_drv.h"
 
-static void virtio_pci_kick_out_firmware_fb(struct pci_dev *pci_dev)
-{
-	struct apertures_struct *ap;
-	bool primary;
-
-	ap = alloc_apertures(1);
-	if (!ap)
-		return;
-
-	ap->ranges[0].base = pci_resource_start(pci_dev, 0);
-	ap->ranges[0].size = pci_resource_len(pci_dev, 0);
-
-	primary = pci_dev->resource[PCI_ROM_RESOURCE].flags
-		& IORESOURCE_ROM_SHADOW;
-
-	remove_conflicting_framebuffers(ap, "virtiodrmfb", primary);
-
-	kfree(ap);
-}
-
  int drm_virtio_init(struct drm_driver *driver, struct virtio_device *vdev)
  {
  	struct drm_device *dev;

drivers/gpu/drm/virtio/virtgpu_drm_bus.c int drm_virtio_init(struct drm_driver *driver, struct virtio_device *vdev) · line 52

Quoted 9 lines
drivers/gpu/drm/virtio/virtgpu_drm_bus.c +1 -2
@@ -65,8 +46,7 @@ int drm_virtio_init(struct drm_driver *driver, struct virtio_device *vdev)
  		DRM_INFO("pci: %s detected\n",
  			 vga ? "virtio-vga" : "virtio-gpu-pci");
  		dev->pdev = pdev;
-		if (vga)
-			virtio_pci_kick_out_firmware_fb(pdev);
+		sysfb_evict_conflicts_pci(pdev);
  	}
 
  	ret = drm_dev_register(dev, 0);

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#14 lore raw

PATCH v5 6/7 drm: add SimpleDRM driver

In reply to David Herrmann

The SimpleDRM driver binds to simple-framebuffer devices and provides a DRM/KMS API. It provides only a single CRTC+encoder+connector combination plus one initial mode.

Userspace can create dumb-buffers which can be blit into the real framebuffer similar to UDL. No access to the real framebuffer is allowed (compared to earlier version of this driver) to avoid security issues. Furthermore, this way we can support arbitrary modes as long as we have a conversion-helper.

---
 MAINTAINERS                                  |   6 +
 drivers/gpu/drm/Kconfig                      |   2 +
 drivers/gpu/drm/Makefile                     |   1 +
 drivers/gpu/drm/simpledrm/Kconfig            |  19 ++
 drivers/gpu/drm/simpledrm/Makefile           |   8 +
 drivers/gpu/drm/simpledrm/simpledrm.h        |  83 +++++
 drivers/gpu/drm/simpledrm/simpledrm_damage.c | 194 +++++++++++
 drivers/gpu/drm/simpledrm/simpledrm_drv.c    | 464 +++++++++++++++++++++++++++
 drivers/gpu/drm/simpledrm/simpledrm_gem.c    | 109 +++++++
 drivers/gpu/drm/simpledrm/simpledrm_kms.c    | 263 +++++++++++++++
 drivers/gpu/drm/simpledrm/simpledrm_of.c     | 265 +++++++++++++++
 11 files changed, 1414 insertions(+)
 create mode 100644 drivers/gpu/drm/simpledrm/Kconfig
 create mode 100644 drivers/gpu/drm/simpledrm/Makefile
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm.h
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_damage.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_drv.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_gem.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_kms.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_of.c
MAINTAINERS +6 -0
index 0bbe4b1..408863d 100644
@@ -4140,6 +4140,12 @@ S:	Orphan / Obsolete
 F:	drivers/gpu/drm/savage/
 F:	include/uapi/drm/savage_drm.h
 
+DRM DRIVER FOR SIMPLE FRAMEBUFFER DEVICES
+M:	David Herrmann <[email protected]>
+L:	[email protected]
+S:	Maintained
+F:	drivers/gpu/drm/simpledrm/
+
 DRM DRIVER FOR SIS VIDEO CARDS
 S:	Orphan / Obsolete
 F:	drivers/gpu/drm/sis/
drivers/gpu/drm/Kconfig +2 -0
index f27f9b5..61cbcd1 100644
@@ -291,3 +291,5 @@ source "drivers/gpu/drm/arc/Kconfig"
 source "drivers/gpu/drm/hisilicon/Kconfig"
 
 source "drivers/gpu/drm/mediatek/Kconfig"
+
+source "drivers/gpu/drm/simpledrm/Kconfig"
drivers/gpu/drm/Makefile +1 -0
index 0238bf8..3e6fe99 100644
@@ -83,3 +83,4 @@ obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/
 obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/
 obj-$(CONFIG_DRM_ARCPGU)+= arc/
 obj-y			+= hisilicon/
+obj-y			+= simpledrm/
drivers/gpu/drm/simpledrm/Kconfig new file +19 -0
new file mode 100644
index 0000000..f45b25d
@@ -0,0 +1,19 @@
+config DRM_SIMPLEDRM
+	tristate "Simple firmware framebuffer DRM driver"
+	depends on DRM
+	select DRM_KMS_HELPER
+	help
+	  SimpleDRM can run on all systems with pre-initialized graphics
+	  hardware. It uses a framebuffer that was initialized during
+	  firmware boot. No page-flipping, modesetting or other advanced
+	  features are available. However, other DRM drivers can be loaded
+	  later and take over from SimpleDRM if they provide real hardware
+	  support.
+
+	  SimpleDRM supports "simple-framebuffer" DeviceTree objects and
+	  compatible platform framebuffers.
+
+	  If unsure, say Y.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called simpledrm.
drivers/gpu/drm/simpledrm/Makefile new file +8 -0
new file mode 100644
index 0000000..d7b179d
@@ -0,0 +1,8 @@
+simpledrm-y := \
+	simpledrm_damage.o \
+	simpledrm_drv.o \
+	simpledrm_gem.o \
+	simpledrm_kms.o \
+	simpledrm_of.o
+
+obj-$(CONFIG_DRM_SIMPLEDRM) := simpledrm.o
drivers/gpu/drm/simpledrm/simpledrm.h new file +83 -0

83 lines not on this page · raw message

drivers/gpu/drm/simpledrm/simpledrm_damage.c new file +194 -0

194 lines not on this page · raw message

drivers/gpu/drm/simpledrm/simpledrm_drv.c new file +464 -0

464 lines not on this page · raw message

drivers/gpu/drm/simpledrm/simpledrm_gem.c new file +109 -0

109 lines not on this page · raw message

drivers/gpu/drm/simpledrm/simpledrm_kms.c new file +263 -0

263 lines not on this page · raw message

drivers/gpu/drm/simpledrm/simpledrm_of.c new file +265 -0

265 lines not on this page · raw message

Signature · 6 lines
2.9.3

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
#15 lore raw

Re: [PATCH v5 6/7] drm: add SimpleDRM driver

Quoted 494 lines · David Herrmann

The SimpleDRM driver binds to simple-framebuffer devices and provides a DRM/KMS API. It provides only a single CRTC+encoder+connector combination plus one initial mode.

Userspace can create dumb-buffers which can be blit into the real framebuffer similar to UDL. No access to the real framebuffer is allowed (compared to earlier version of this driver) to avoid security issues. Furthermore, this way we can support arbitrary modes as long as we have a conversion-helper.

---
 MAINTAINERS                                  |   6 +
 drivers/gpu/drm/Kconfig                      |   2 +
 drivers/gpu/drm/Makefile                     |   1 +
 drivers/gpu/drm/simpledrm/Kconfig            |  19 ++
 drivers/gpu/drm/simpledrm/Makefile           |   8 +
 drivers/gpu/drm/simpledrm/simpledrm.h        |  83 +++++
 drivers/gpu/drm/simpledrm/simpledrm_damage.c | 194 +++++++++++
 drivers/gpu/drm/simpledrm/simpledrm_drv.c    | 464 +++++++++++++++++++++++++++
 drivers/gpu/drm/simpledrm/simpledrm_gem.c    | 109 +++++++
 drivers/gpu/drm/simpledrm/simpledrm_kms.c    | 263 +++++++++++++++
 drivers/gpu/drm/simpledrm/simpledrm_of.c     | 265 +++++++++++++++
 11 files changed, 1414 insertions(+)
 create mode 100644 drivers/gpu/drm/simpledrm/Kconfig
 create mode 100644 drivers/gpu/drm/simpledrm/Makefile
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm.h
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_damage.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_drv.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_gem.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_kms.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_of.c
MAINTAINERS +6 -0
index 0bbe4b1..408863d 100644
@@ -4140,6 +4140,12 @@ S:       Orphan / Obsolete
 F:     drivers/gpu/drm/savage/
 F:     include/uapi/drm/savage_drm.h
 
+DRM DRIVER FOR SIMPLE FRAMEBUFFER DEVICES
+M:     David Herrmann <[email protected]>
+L:     [email protected]
+S:     Maintained
+F:     drivers/gpu/drm/simpledrm/
+
 DRM DRIVER FOR SIS VIDEO CARDS
 S:     Orphan / Obsolete
 F:     drivers/gpu/drm/sis/
drivers/gpu/drm/Kconfig +2 -0
index f27f9b5..61cbcd1 100644
@@ -291,3 +291,5 @@ source "drivers/gpu/drm/arc/Kconfig"
 source "drivers/gpu/drm/hisilicon/Kconfig"
 
 source "drivers/gpu/drm/mediatek/Kconfig"
+
+source "drivers/gpu/drm/simpledrm/Kconfig"
drivers/gpu/drm/Makefile +1 -0
index 0238bf8..3e6fe99 100644
@@ -83,3 +83,4 @@ obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/
 obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/
 obj-$(CONFIG_DRM_ARCPGU)+= arc/
 obj-y                  += hisilicon/
+obj-y                  += simpledrm/
drivers/gpu/drm/simpledrm/Kconfig new file +19 -0
new file mode 100644
index 0000000..f45b25d
@@ -0,0 +1,19 @@
+config DRM_SIMPLEDRM
+       tristate "Simple firmware framebuffer DRM driver"
+       depends on DRM
+       select DRM_KMS_HELPER
+       help
+         SimpleDRM can run on all systems with pre-initialized graphics
+         hardware. It uses a framebuffer that was initialized during
+         firmware boot. No page-flipping, modesetting or other advanced
+         features are available. However, other DRM drivers can be loaded
+         later and take over from SimpleDRM if they provide real hardware
+         support.
+
+         SimpleDRM supports "simple-framebuffer" DeviceTree objects and
+         compatible platform framebuffers.
+
+         If unsure, say Y.
+
+         To compile this driver as a module, choose M here: the
+         module will be called simpledrm.
drivers/gpu/drm/simpledrm/Makefile new file +8 -0
new file mode 100644
index 0000000..d7b179d
@@ -0,0 +1,8 @@
+simpledrm-y := \
+       simpledrm_damage.o \
+       simpledrm_drv.o \
+       simpledrm_gem.o \
+       simpledrm_kms.o \
+       simpledrm_of.o
+
+obj-$(CONFIG_DRM_SIMPLEDRM) := simpledrm.o
drivers/gpu/drm/simpledrm/simpledrm.h new file +83 -0
new file mode 100644
index 0000000..ed6d725
@@ -0,0 +1,83 @@
+#ifndef __SDRM_SIMPLEDRM_H
+#define __SDRM_SIMPLEDRM_H
+
+/*
+ * Copyright (C) 2012-2016 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_gem.h>
+#include <drm/drm_simple_kms_helper.h>
+#include <linux/atomic.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+
+struct clk;
+struct regulator;
+struct simplefb_format;
+
+struct sdrm_hw {
+       struct mutex lock;
+       u32 width;
+       u32 height;
+       u32 stride;
+       u32 bpp;
+       u32 format;
+       unsigned long base;
+       unsigned long size;
+       void *map;
+};
+
+struct sdrm_bo {
+       struct drm_gem_object base;
+       struct page **pages;
+       void *vmapping;
+};
+
+struct sdrm_fb {
+       struct drm_framebuffer base;
+       struct sdrm_bo *bo;
+};
+
+struct sdrm_device {
+       atomic_t n_used;
+       struct drm_device *ddev;
+       struct sdrm_hw *hw;
+
+       size_t n_clks;
+       size_t n_regulators;
+       struct clk **clks;
+       struct regulator **regulators;
+
+       struct drm_simple_display_pipe pipe;
+       struct drm_connector conn;
+};
+
+void sdrm_of_bootstrap(void);
+int sdrm_of_bind(struct sdrm_device *sdrm);
+void sdrm_of_unbind(struct sdrm_device *sdrm);
+
+int sdrm_kms_bind(struct sdrm_device *sdrm);
+void sdrm_kms_unbind(struct sdrm_device *sdrm);
+
+void sdrm_dirty(struct sdrm_fb *fb, u32 x, u32 y, u32 width, u32 height);
+
+struct sdrm_bo *sdrm_bo_new(struct drm_device *ddev, size_t size);
+void sdrm_bo_free(struct drm_gem_object *obj);
+int sdrm_bo_vmap(struct sdrm_bo *bo);
+
+int sdrm_dumb_create(struct drm_file *dfile,
+                    struct drm_device *ddev,
+                    struct drm_mode_create_dumb *arg);
+int sdrm_dumb_map_offset(struct drm_file *dfile,
+                        struct drm_device *ddev,
+                        uint32_t handle,
+                        uint64_t *offset);
+
+#endif /* __SDRM_SIMPLEDRM_H */
drivers/gpu/drm/simpledrm/simpledrm_damage.c new file +194 -0
new file mode 100644
index 0000000..4f7af5d
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2012-2016 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <asm/unaligned.h>
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <linux/kernel.h>
+#include "simpledrm.h"
+
+static inline void sdrm_put(u8 *dst, u32 four_cc, u16 r, u16 g, u16 b)
+{
+       switch (four_cc) {
+       case DRM_FORMAT_RGB565:
+               r >>= 11;
+               g >>= 10;
+               b >>= 11;
+               put_unaligned((u16)((r << 11) | (g << 5) | b), (u16 *)dst);
+               break;
+       case DRM_FORMAT_XRGB1555:
+       case DRM_FORMAT_ARGB1555:
+               r >>= 11;
+               g >>= 11;
+               b >>= 11;
+               put_unaligned((u16)((r << 10) | (g << 5) | b), (u16 *)dst);
+               break;
+       case DRM_FORMAT_RGB888:
+               r >>= 8;
+               g >>= 8;
+               b >>= 8;
+#ifdef __LITTLE_ENDIAN
+               dst[2] = r;
+               dst[1] = g;
+               dst[0] = b;
+#elif defined(__BIG_ENDIAN)
+               dst[0] = r;
+               dst[1] = g;
+               dst[2] = b;
+#endif
+               break;
+       case DRM_FORMAT_XRGB8888:
+       case DRM_FORMAT_ARGB8888:
+               r >>= 8;
+               g >>= 8;
+               b >>= 8;
+               put_unaligned((u32)((r << 16) | (g << 8) | b), (u32 *)dst);
+               break;
+       case DRM_FORMAT_ABGR8888:
+               r >>= 8;
+               g >>= 8;
+               b >>= 8;
+               put_unaligned((u32)((b << 16) | (g << 8) | r), (u32 *)dst);
+               break;
+       case DRM_FORMAT_XRGB2101010:
+       case DRM_FORMAT_ARGB2101010:
+               r >>= 4;
+               g >>= 4;
+               b >>= 4;
+               put_unaligned((u32)((r << 20) | (g << 10) | b), (u32 *)dst);
+               break;
+       }
+}
+
+static void sdrm_blit_from_xrgb8888(const u8 *src,
+                                   u32 src_stride,
+                                   u32 src_bpp,
+                                   u8 *dst,
+                                   u32 dst_stride,
+                                   u32 dst_bpp,
+                                   u32 dst_four_cc,
+                                   u32 width,
+                                   u32 height)
+{
+       u32 val, i;
+
+       while (height--) {
+               for (i = 0; i < width; ++i) {
+                       val = get_unaligned((const u32 *)&src[i * src_bpp]);
+                       sdrm_put(&dst[i * dst_bpp], dst_four_cc,
+                                (val & 0x00ff0000U) >> 8,
+                                (val & 0x0000ff00U),
+                                (val & 0x000000ffU) << 8);
+               }
+
+               src += src_stride;
+               dst += dst_stride;
+       }
+}
+
+static void sdrm_blit_from_rgb565(const u8 *src,
+                                 u32 src_stride,
+                                 u32 src_bpp,
+                                 u8 *dst,
+                                 u32 dst_stride,
+                                 u32 dst_bpp,
+                                 u32 dst_four_cc,
+                                 u32 width,
+                                 u32 height)
+{
+       u32 val, i;
+
+       while (height--) {
+               for (i = 0; i < width; ++i) {
+                       val = get_unaligned((const u16 *)&src[i * src_bpp]);
+                       sdrm_put(&dst[i * dst_bpp], dst_four_cc,
+                                (val & 0xf800),
+                                (val & 0x07e0) << 5,
+                                (val & 0x001f) << 11);
+               }
+
+               src += src_stride;
+               dst += dst_stride;
+       }
+}
+
+static void sdrm_blit_lines(const u8 *src,
+                           u32 src_stride,
+                           u8 *dst,
+                           u32 dst_stride,
+                           u32 bpp,
+                           u32 width,
+                           u32 height)
+{
+       u32 len;
+
+       len = width * bpp;
+
+       while (height--) {
+               memcpy(dst, src, len);
+               src += src_stride;
+               dst += dst_stride;
+       }
+}
+
+static void sdrm_blit(struct sdrm_hw *hw,
+                     struct sdrm_fb *fb,
+                     u32 x,
+                     u32 y,
+                     u32 width,
+                     u32 height)
+{
+       u32 src_bpp, dst_bpp;
+       u8 *src, *dst;
+
+       src = fb->bo->vmapping;
+       src_bpp = DIV_ROUND_UP(fb->base.bits_per_pixel, 8);
+       src += fb->base.offsets[0] + y * fb->base.pitches[0] + x * src_bpp;
+
+       dst = hw->map;
+       dst_bpp = DIV_ROUND_UP(hw->bpp, 8);
+       dst += y * hw->stride + x * dst_bpp;
+
+       if (fb->base.pixel_format == hw->format) {
+               /* if formats are identical, do a line-by-line copy.. */
+               sdrm_blit_lines(src, fb->base.pitches[0],
+                               dst, hw->stride, src_bpp, width, height);
+       } else {
+               /* ..otherwise call slow blit-function */
+               switch (fb->base.pixel_format) {
+               case DRM_FORMAT_ARGB8888:
+               case DRM_FORMAT_XRGB8888:
+                       sdrm_blit_from_xrgb8888(src, fb->base.pitches[0],
+                                               src_bpp, dst, hw->stride,
+                                               dst_bpp, hw->format,
+                                               width, height);
+                       break;
+               case DRM_FORMAT_RGB565:
+                       sdrm_blit_from_rgb565(src, fb->base.pitches[0],
+                                             src_bpp, dst, hw->stride,
+                                             dst_bpp, hw->format,
+                                             width, height);
+                       break;
+               }
+       }
+}
+
+void sdrm_dirty(struct sdrm_fb *fb, u32 x, u32 y, u32 width, u32 height)
+{
+       struct sdrm_device *sdrm = fb->base.dev->dev_private;
+
+       if (WARN_ON(!fb->bo->vmapping))
+               return;
+
+       mutex_lock(&sdrm->hw->lock);
+       if (sdrm->hw->map)
+               sdrm_blit(sdrm->hw, fb, x, y, width, height);
+       mutex_unlock(&sdrm->hw->lock);
+}
drivers/gpu/drm/simpledrm/simpledrm_drv.c new file +91 -0
new file mode 100644
index 0000000..d569120
@@ -0,0 +1,464 @@
+/*
+ * Copyright (C) 2012-2016 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <drm/drmP.h>
+#include <linux/atomic.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_data/simplefb.h>
+#include <linux/string.h>
+#include "simpledrm.h"
+
+static struct drm_driver sdrm_drm_driver;
+static DEFINE_MUTEX(sdrm_lock);
+
+static int sdrm_hw_identify(struct platform_device *pdev,
+                           struct simplefb_platform_data *modep,
+                           struct simplefb_format *formatp,
+                           struct resource **memp,
+                           u32 *bppp)
+{
+       static const struct simplefb_format valid_formats[] = SIMPLEFB_FORMATS;
+       struct simplefb_platform_data pm = {}, *mode = pdev->dev.platform_data;
+       struct device_node *np = pdev->dev.of_node;
+       const struct simplefb_format *format = NULL;
+       struct resource *mem;
+       unsigned int depth;
+       int r, bpp;
+       size_t i;
+
+       if (!mode) {
+               if (!np)
+                       return -ENODEV;
+
+               mode = &pm;
+
+               r = of_property_read_u32(np, "width", &mode->width);
+               if (r >= 0)
+                       r = of_property_read_u32(np, "height", &mode->height);
+               if (r >= 0)
+                       r = of_property_read_u32(np, "stride", &mode->stride);
+               if (r >= 0)
+                       r = of_property_read_string(np, "format",
+                                                   &mode->format);
+               if (r < 0)
+                       return r;
+       }
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!mem)
+               return -ENODEV;
+
+       for (i = 0; i < ARRAY_SIZE(valid_formats); ++i) {
+               if (!strcmp(mode->format, valid_formats[i].name)) {
+                       format = &valid_formats[i];
+                       break;
+               }
+       }
+
+       if (!format)
+               return -ENODEV;
+
+       switch (format->fourcc) {
+       case DRM_FORMAT_RGB565:
+       case DRM_FORMAT_XRGB1555:
+       case DRM_FORMAT_ARGB1555:
+       case DRM_FORMAT_RGB888:
+       case DRM_FORMAT_XRGB8888:
+       case DRM_FORMAT_ARGB8888:
+       case DRM_FORMAT_ABGR8888:
+       case DRM_FORMAT_XRGB2101010:
+       case DRM_FORMAT_ARGB2101010:
+               /*
+                * You must adjust sdrm_put() whenever you add a new format
+                * here, otherwise, blitting operations will not work.
+                * Furthermore, include/linux/platform_data/simplefb.h needs
+                * to be adjusted so the platform-device actually allows this
+                * format.
+                */
+               break;

drivers/gpu/drm/simpledrm/simpledrm_drv.c line 101

Quoted 10 lines
drivers/gpu/drm/simpledrm/simpledrm_drv.c new file +10 -0
+       default:
+               return -ENODEV;
+       }
+
+       drm_fb_get_bpp_depth(format->fourcc, &depth, &bpp);
+       if (!bpp)
+               return -ENODEV;
+       if (resource_size(mem) < mode->stride * mode->height)
+               return -ENODEV;
+       if ((bpp + 7) / 8 * mode->width > mode->stride)

DIV_ROUND_UP?

Quoted 439 lines
drivers/gpu/drm/simpledrm/simpledrm_drv.c new file +363 -0
+               return -ENODEV;
+
+       *modep = *mode;
+       *formatp = *format;
+       *memp = mem;
+       *bppp = bpp;
+       return 0;
+}
+
+static struct sdrm_hw *sdrm_hw_new(const struct simplefb_platform_data *mode,
+                                  const struct simplefb_format *format,
+                                  const struct resource *mem,
+                                  u32 bpp)
+{
+       struct sdrm_hw *hw;
+
+       hw = kzalloc(sizeof(*hw), GFP_KERNEL);
+       if (!hw)
+               return ERR_PTR(-ENOMEM);
+
+       mutex_init(&hw->lock);
+       hw->width = mode->width;
+       hw->height = mode->height;
+       hw->stride = mode->stride;
+       hw->bpp = bpp;
+       hw->format = format->fourcc;
+       hw->base = mem->start;
+       hw->size = resource_size(mem);
+
+       return hw;
+}
+
+static struct sdrm_hw *sdrm_hw_free(struct sdrm_hw *hw)
+{
+       if (!hw)
+               return NULL;
+
+       WARN_ON(hw->map);
+       mutex_destroy(&hw->lock);
+       kfree(hw);
+
+       return NULL;
+}
+
+static int sdrm_hw_bind(struct sdrm_hw *hw)
+{
+       mutex_lock(&hw->lock);
+       if (!hw->map)
+               hw->map = ioremap_wc(hw->base, hw->size);
+       mutex_unlock(&hw->lock);
+
+       return hw->map ? 0 : -EIO;
+}
+
+static void sdrm_hw_unbind(struct sdrm_hw *hw)
+{
+       if (!hw)
+               return;
+
+       mutex_lock(&hw->lock);
+       if (hw->map) {
+               iounmap(hw->map);
+               hw->map = NULL;
+       }
+       mutex_unlock(&hw->lock);
+}
+
+static struct sdrm_device *sdrm_device_free(struct sdrm_device *sdrm)
+{
+       if (!sdrm)
+               return NULL;
+
+       WARN_ON(atomic_read(&sdrm->n_used) != INT_MIN);
+       sdrm->hw = sdrm_hw_free(sdrm->hw);
+       drm_dev_unref(sdrm->ddev);
+       kfree(sdrm);
+
+       return NULL;
+}
+
+static struct sdrm_device *sdrm_device_new(struct platform_device *pdev,
+                                          struct sdrm_hw *hw)
+{
+       struct sdrm_device *sdrm;
+       int r;
+
+       sdrm = kzalloc(sizeof(*sdrm), GFP_KERNEL);
+       if (!sdrm)
+               return ERR_PTR(-ENOMEM);
+
+       atomic_set(&sdrm->n_used, INT_MIN);
+
+       sdrm->ddev = drm_dev_alloc(&sdrm_drm_driver, &pdev->dev);
+       if (!sdrm->ddev) {
+               r = -ENOMEM;
+               goto error;
+       }
+
+       sdrm->ddev->dev_private = sdrm;
+       sdrm->hw = hw;
+
+       return sdrm;
+
+error:
+       sdrm_device_free(sdrm);
+       return ERR_PTR(r);
+}
+
+static void sdrm_device_unbind(struct sdrm_device *sdrm)
+{
+       if (sdrm) {
+               sdrm_kms_unbind(sdrm);
+               sdrm_hw_unbind(sdrm->hw);
+               sdrm_of_unbind(sdrm);
+       }
+}
+
+static int sdrm_device_bind(struct sdrm_device *sdrm)
+{
+       int r;
+
+       r = sdrm_of_bind(sdrm);
+       if (r < 0)
+               goto error;
+
+       r = sdrm_hw_bind(sdrm->hw);
+       if (r < 0)
+               goto error;
+
+       r = sdrm_kms_bind(sdrm);
+       if (r < 0)
+               goto error;
+
+       return 0;
+
+error:
+       sdrm_device_unbind(sdrm);
+       return r;
+}
+
+static int sdrm_device_acquire(struct sdrm_device *sdrm)
+{
+       return (sdrm && atomic_inc_unless_negative(&sdrm->n_used))
+               ? 0 : -ENODEV;
+}
+
+static void sdrm_device_release(struct sdrm_device *sdrm)
+{
+       if (sdrm && atomic_dec_return(&sdrm->n_used) == INT_MIN) {
+               sdrm_device_unbind(sdrm);
+               sdrm_device_free(sdrm);
+       }
+}
+
+static int sdrm_fop_open(struct inode *inode, struct file *file)
+{
+       struct drm_device *ddev;
+       int r;
+
+       mutex_lock(&sdrm_lock);
+       r = drm_open(inode, file);
+       if (r >= 0) {
+               ddev = file->private_data;
+               r = sdrm_device_acquire(ddev->dev_private);
+               if (r < 0)
+                       drm_release(inode, file);
+       }
+       mutex_unlock(&sdrm_lock);
+
+       return r;
+}
+
+static int sdrm_fop_release(struct inode *inode, struct file *file)
+{
+       struct drm_file *dfile = file->private_data;
+       struct drm_device *ddev = dfile->minor->dev;
+       struct sdrm_device *sdrm = ddev->dev_private;
+       int res;
+
+       res = drm_release(inode, file);
+       sdrm_device_release(sdrm);
+       return res;
+}
+
+static int sdrm_fop_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct drm_file *dfile = file->private_data;
+       struct drm_device *dev = dfile->minor->dev;
+       struct drm_gem_object *obj = NULL;
+       struct drm_vma_offset_node *node;
+       int r;
+
+       drm_vma_offset_lock_lookup(dev->vma_offset_manager);
+       node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager,
+                                                 vma->vm_pgoff,
+                                                 vma_pages(vma));
+       if (likely(node)) {
+               obj = container_of(node, struct drm_gem_object, vma_node);
+               if (!kref_get_unless_zero(&obj->refcount))
+                       obj = NULL;
+       }
+       drm_vma_offset_unlock_lookup(dev->vma_offset_manager);
+
+       if (!obj)
+               return -EINVAL;
+
+       if (!drm_vma_node_is_allowed(node, dfile)) {
+               drm_gem_object_unreference_unlocked(obj);
+               return -EACCES;
+       }
+
+       if (vma->vm_file)
+               fput(vma->vm_file);
+       vma->vm_file = get_file(obj->filp);
+       vma->vm_pgoff = 0;
+
+       r = obj->filp->f_op->mmap(obj->filp, vma);
+       drm_gem_object_unreference_unlocked(obj);
+       return r;
+}
+
+static int sdrm_simplefb_probe(struct platform_device *pdev)
+{
+       struct simplefb_platform_data hw_mode;
+       struct simplefb_format hw_format;
+       struct sdrm_device *sdrm = NULL;
+       struct sdrm_hw *hw = NULL;
+       struct resource *hw_mem;
+       u32 hw_bpp;
+       int r;
+
+       r = sdrm_hw_identify(pdev, &hw_mode, &hw_format, &hw_mem, &hw_bpp);
+       if (r < 0)
+               goto error;
+
+       hw = sdrm_hw_new(&hw_mode, &hw_format, hw_mem, hw_bpp);
+       if (IS_ERR(hw)) {
+               r = PTR_ERR(hw);
+               hw = NULL;
+               goto error;
+       }
+
+       sdrm = sdrm_device_new(pdev, hw);
+       if (IS_ERR(sdrm)) {
+               r = PTR_ERR(sdrm);
+               sdrm = NULL;
+               goto error;
+       }
+       hw = NULL;
+       platform_set_drvdata(pdev, sdrm);
+
+       r = sdrm_device_bind(sdrm);
+       if (r < 0)
+               goto error;
+
+       /* mark device as enabled and acquire bus ref */
+       WARN_ON(atomic_read(&sdrm->n_used) != INT_MIN);
+       atomic_set(&sdrm->n_used, 1);
+
+       r = drm_dev_register(sdrm->ddev, 0);
+       if (r < 0) {
+               /* mark device as disabled and drop bus ref */
+               WARN_ON(atomic_add_return(INT_MIN, &sdrm->n_used) != INT_MIN);
+               sdrm_device_release(sdrm);
+               return r;
+       }
+
+       dev_info(sdrm->ddev->dev, "initialized %s on minor %d\n",
+                sdrm->ddev->driver->name, sdrm->ddev->primary->index);
+
+       return 0;
+
+error:
+       sdrm_device_unbind(sdrm);
+       sdrm_device_free(sdrm);
+       sdrm_hw_free(hw);
+       return r;
+}
+
+static int sdrm_simplefb_remove(struct platform_device *pdev)
+{
+       struct sdrm_device *sdrm = platform_get_drvdata(pdev);
+
+       /* mark device as disabled */
+       atomic_add(INT_MIN, &sdrm->n_used);
+       sdrm_hw_unbind(sdrm->hw);
+
+       mutex_lock(&sdrm_lock);
+       drm_dev_unregister(sdrm->ddev);
+       sdrm_device_release(sdrm);
+       mutex_unlock(&sdrm_lock);
+
+       return 0;
+}
+
+static const struct file_operations sdrm_drm_fops = {
+       .owner = THIS_MODULE,
+       .open = sdrm_fop_open,
+       .release = sdrm_fop_release,
+       .mmap = sdrm_fop_mmap,
+       .poll = drm_poll,
+       .read = drm_read,
+       .unlocked_ioctl = drm_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
+       .llseek = noop_llseek,
+};
+
+static struct drm_driver sdrm_drm_driver = {
+       .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
+       .fops = &sdrm_drm_fops,
+
+       .gem_free_object = sdrm_bo_free,
+
+       .dumb_create = sdrm_dumb_create,
+       .dumb_map_offset = sdrm_dumb_map_offset,
+       .dumb_destroy = drm_gem_dumb_destroy,
+
+       .name = "simpledrm",
+       .desc = "Simple firmware framebuffer DRM driver",
+       .date = "20160901",
+};
+
+static const struct of_device_id sdrm_simplefb_of_match[] = {
+       { .compatible = "simple-framebuffer", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, sdrm_simplefb_of_match);
+
+static struct platform_driver sdrm_simplefb_driver = {
+       .probe = sdrm_simplefb_probe,
+       .remove = sdrm_simplefb_remove,
+       .driver = {
+               .name = "simple-framebuffer",
+               .mod_name = KBUILD_MODNAME,
+               .owner = THIS_MODULE,
+               .of_match_table = sdrm_simplefb_of_match,
+       },
+};
+
+static int __init sdrm_init(void)
+{
+       int r;
+
+       r = platform_driver_register(&sdrm_simplefb_driver);
+       if (r < 0)
+               return r;
+
+       sdrm_of_bootstrap();
+       return 0;
+}
+
+static void __exit sdrm_exit(void)
+{
+       platform_driver_unregister(&sdrm_simplefb_driver);
+}
+
+module_init(sdrm_init);
+module_exit(sdrm_exit);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Simple firmware framebuffer DRM driver");
+MODULE_ALIAS("platform:simple-framebuffer");
drivers/gpu/drm/simpledrm/simpledrm_gem.c new file +70 -0
new file mode 100644
index 0000000..4aaae6e
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2012-2016 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <drm/drmP.h>
+#include <drm/drm_gem.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include "simpledrm.h"
+
+struct sdrm_bo *sdrm_bo_new(struct drm_device *ddev, size_t size)
+{
+       struct sdrm_bo *bo;
+
+       WARN_ON(!size || (size & ~PAGE_MASK) != 0);
+
+       bo = kzalloc(sizeof(*bo), GFP_KERNEL);
+       if (!bo)
+               return NULL;
+
+       if (drm_gem_object_init(ddev, &bo->base, size)) {
+               kfree(bo);
+               return NULL;
+       }
+
+       return bo;
+}
+
+void sdrm_bo_free(struct drm_gem_object *dobj)
+{
+       struct sdrm_bo *bo = container_of(dobj, struct sdrm_bo, base);
+
+       if (bo->vmapping)
+               vunmap(bo->vmapping);
+       if (bo->pages)
+               drm_gem_put_pages(dobj, bo->pages, false, false);
+       drm_gem_object_release(dobj);
+       kfree(bo);
+}
+
+int sdrm_bo_vmap(struct sdrm_bo *bo)
+{
+       int r;
+
+       if (!bo->pages) {
+               bo->pages = drm_gem_get_pages(&bo->base);
+               if (IS_ERR(bo->pages)) {
+                       r = PTR_ERR(bo->pages);
+                       bo->pages = NULL;
+                       return r;
+               }
+       }
+
+       if (!bo->vmapping) {
+               bo->vmapping = vmap(bo->pages, bo->base.size / PAGE_SIZE, 0,
+                                   PAGE_KERNEL);
+               if (!bo->vmapping)
+                       return -ENOMEM;
+       }
+
+       return 0;
+}

drivers/gpu/drm/simpledrm/simpledrm_gem.c line 80

Quoted 10 lines
drivers/gpu/drm/simpledrm/simpledrm_gem.c new file +10 -0
+
+int sdrm_dumb_create(struct drm_file *dfile,
+                    struct drm_device *ddev,
+                    struct drm_mode_create_dumb *args)
+{
+       struct sdrm_bo *bo;
+       int r;
+
+       /* overflow checks are done by DRM core */
+       args->pitch = (args->bpp + 7) / 8 * args->width;

DIV_ROUND_UP?

Quoted 168 lines
drivers/gpu/drm/simpledrm/simpledrm_gem.c new file +29 -0
+       args->size = PAGE_ALIGN(args->pitch * args->height);
+
+       bo = sdrm_bo_new(ddev, args->size);
+       if (!bo)
+               return -ENOMEM;
+
+       r = drm_gem_handle_create(dfile, &bo->base, &args->handle);
+       drm_gem_object_unreference_unlocked(&bo->base);
+       return r;
+}
+
+int sdrm_dumb_map_offset(struct drm_file *dfile,
+                        struct drm_device *ddev,
+                        uint32_t handle,
+                        uint64_t *offset)
+{
+       struct drm_gem_object *dobj;
+       int r;
+
+       dobj = drm_gem_object_lookup(dfile, handle);
+       if (!dobj)
+               return -ENOENT;
+
+       r = drm_gem_create_mmap_offset(dobj);
+       if (r >= 0)
+               *offset = drm_vma_node_offset_addr(&dobj->vma_node);
+       drm_gem_object_unreference_unlocked(dobj);
+       return r;
+}
drivers/gpu/drm/simpledrm/simpledrm_kms.c new file +133 -0
new file mode 100644
index 0000000..00101c9
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2012-2016 Red Hat, Inc.
+ * Copyright (C) 2016 Noralf Trønnes
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_gem.h>
+#include <drm/drm_simple_kms_helper.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include "simpledrm.h"
+
+static const uint32_t sdrm_formats[] = {
+       DRM_FORMAT_RGB565,
+       DRM_FORMAT_ARGB8888,
+       DRM_FORMAT_XRGB8888,
+};
+
+static int sdrm_conn_get_modes(struct drm_connector *conn)
+{
+       struct sdrm_device *sdrm = conn->dev->dev_private;
+       struct drm_display_mode *mode;
+
+       mode = drm_cvt_mode(sdrm->ddev, sdrm->hw->width, sdrm->hw->height,
+                           60, false, false, false);
+       if (!mode)
+               return 0;
+
+       mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+       drm_mode_set_name(mode);
+       drm_mode_probed_add(conn, mode);
+
+       return 1;
+}
+
+static const struct drm_connector_helper_funcs sdrm_conn_hfuncs = {
+       .get_modes      = sdrm_conn_get_modes,
+       .best_encoder   = drm_atomic_helper_best_encoder,
+};
+
+static enum drm_connector_status sdrm_conn_detect(struct drm_connector *conn,
+                                                 bool force)
+{
+       /*
+        * We simulate an always connected monitor. simple-fb doesn't
+        * provide any way to detect whether the connector is active. Hence,
+        * signal DRM core that it is always connected.
+        */
+       return connector_status_connected;
+}
+
+static const struct drm_connector_funcs sdrm_conn_ops = {
+       .dpms                   = drm_atomic_helper_connector_dpms,
+       .reset                  = drm_atomic_helper_connector_reset,
+       .detect                 = sdrm_conn_detect,
+       .fill_modes             = drm_helper_probe_single_connector_modes,
+       .destroy                = drm_connector_cleanup,
+       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+       .atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
+};
+
+static void sdrm_crtc_send_vblank_event(struct drm_crtc *crtc)
+{
+       if (crtc->state && crtc->state->event) {
+               spin_lock_irq(&crtc->dev->event_lock);
+               drm_crtc_send_vblank_event(crtc, crtc->state->event);
+               spin_unlock_irq(&crtc->dev->event_lock);
+               crtc->state->event = NULL;
+       }
+}
+
+void sdrm_display_pipe_update(struct drm_simple_display_pipe *pipe,
+                             struct drm_plane_state *plane_state)
+{
+       struct drm_framebuffer *dfb = pipe->plane.state->fb;
+       struct sdrm_fb *fb;
+
+       sdrm_crtc_send_vblank_event(&pipe->crtc);
+
+       if (dfb) {
+               fb = container_of(dfb, struct sdrm_fb, base);
+               pipe->plane.fb = dfb;
+               sdrm_dirty(fb, 0, 0, dfb->width, dfb->height);
+       }
+}
+
+static void sdrm_display_pipe_enable(struct drm_simple_display_pipe *pipe,
+                                    struct drm_crtc_state *crtc_state)
+{
+       sdrm_crtc_send_vblank_event(&pipe->crtc);
+}
+
+static void sdrm_display_pipe_disable(struct drm_simple_display_pipe *pipe)
+{
+       sdrm_crtc_send_vblank_event(&pipe->crtc);
+}
+
+static const struct drm_simple_display_pipe_funcs sdrm_pipe_funcs = {
+       .update         = sdrm_display_pipe_update,
+       .enable         = sdrm_display_pipe_enable,
+       .disable        = sdrm_display_pipe_disable,
+};
+
+static int sdrm_fb_create_handle(struct drm_framebuffer *dfb,
+                                struct drm_file *dfile,
+                                unsigned int *handle)
+{
+       struct sdrm_fb *fb = container_of(dfb, struct sdrm_fb, base);
+
+       return drm_gem_handle_create(dfile, &fb->bo->base, handle);
+}
+
+static int sdrm_fb_dirty(struct drm_framebuffer *dfb,
+                        struct drm_file *dfile,
+                        unsigned int flags,
+                        unsigned int color,
+                        struct drm_clip_rect *clips,
+                        unsigned int n_clips)
+{
+       struct sdrm_fb *fb = container_of(dfb, struct sdrm_fb, base);
+       struct sdrm_device *sdrm = dfb->dev->dev_private;
+       unsigned int i;
+

drivers/gpu/drm/simpledrm/simpledrm_kms.c line 143

Quoted 10 lines
drivers/gpu/drm/simpledrm/simpledrm_kms.c new file +10 -0
+       drm_modeset_lock_all(sdrm->ddev);
+       if (dfb == sdrm->pipe.plane.fb) {
+               if (!clips || !n_clips) {
+                       sdrm_dirty(fb, 0, 0, dfb->width, dfb->height);
+               } else {
+                       for (i = 0; i < n_clips; i++) {
+                               if (clips[i].x1 > clips[i].x2 ||
+                                   clips[i].x2 > dfb->width ||
+                                   clips[i].y1 > clips[i].y2 ||
+                                   clips[i].y2 > dfb->height)

As discussed in private, overlapping clip_rects should be cropped to fit the fb, rather than discarded.

Quoted 175 lines
drivers/gpu/drm/simpledrm/simpledrm_kms.c new file +120 -0
+                                       continue;
+
+                               sdrm_dirty(fb, clips[i].x1, clips[i].y1,
+                                          clips[i].x2 - clips[i].x1,
+                                          clips[i].y2 - clips[i].y1);
+                       }
+               }
+       }
+       drm_modeset_unlock_all(sdrm->ddev);
+
+       return 0;
+}
+
+static void sdrm_fb_destroy(struct drm_framebuffer *dfb)
+{
+       struct sdrm_fb *fb = container_of(dfb, struct sdrm_fb, base);
+
+       drm_framebuffer_cleanup(dfb);
+       drm_gem_object_unreference_unlocked(&fb->bo->base);
+       kfree(fb);
+}
+
+static const struct drm_framebuffer_funcs sdrm_fb_ops = {
+       .create_handle          = sdrm_fb_create_handle,
+       .dirty                  = sdrm_fb_dirty,
+       .destroy                = sdrm_fb_destroy,
+};
+
+static struct drm_framebuffer *
+sdrm_fb_create(struct drm_device *ddev,
+              struct drm_file *dfile,
+              const struct drm_mode_fb_cmd2 *cmd)
+{
+       struct drm_gem_object *dobj;
+       struct sdrm_fb *fb = NULL;
+       struct sdrm_bo *bo;
+       int r;
+
+       if (cmd->flags)
+               return ERR_PTR(-EINVAL);
+
+       dobj = drm_gem_object_lookup(dfile, cmd->handles[0]);
+       if (!dobj)
+               return ERR_PTR(-EINVAL);
+
+       bo = container_of(dobj, struct sdrm_bo, base);
+
+       r = sdrm_bo_vmap(bo);
+       if (r < 0)
+               goto error;
+
+       fb = kzalloc(sizeof(*fb), GFP_KERNEL);
+       if (!fb) {
+               r = -ENOMEM;
+               goto error;
+       }
+
+       fb->bo = bo;
+       drm_helper_mode_fill_fb_struct(&fb->base, cmd);
+
+       r = drm_framebuffer_init(ddev, &fb->base, &sdrm_fb_ops);
+       if (r < 0)
+               goto error;
+
+       DRM_DEBUG_KMS("[FB:%d] pixel_format: %s\n", fb->base.base.id,
+                     drm_get_format_name(fb->base.pixel_format));
+
+       return &fb->base;
+
+error:
+       kfree(fb);
+       drm_gem_object_unreference_unlocked(dobj);
+       return ERR_PTR(r);
+}
+
+static const struct drm_mode_config_funcs sdrm_mode_config_ops = {
+       .fb_create              = sdrm_fb_create,
+       .atomic_check           = drm_atomic_helper_check,
+       .atomic_commit          = drm_atomic_helper_commit,
+};
+
+int sdrm_kms_bind(struct sdrm_device *sdrm)
+{
+       struct drm_connector *conn = &sdrm->conn;
+       struct drm_device *ddev = sdrm->ddev;
+       int r;
+
+       drm_mode_config_init(ddev);
+       ddev->mode_config.min_width = sdrm->hw->width;
+       ddev->mode_config.max_width = sdrm->hw->width;
+       ddev->mode_config.min_height = sdrm->hw->height;
+       ddev->mode_config.max_height = sdrm->hw->height;
+       ddev->mode_config.preferred_depth = sdrm->hw->bpp;
+       ddev->mode_config.funcs = &sdrm_mode_config_ops;
+       drm_connector_helper_add(conn, &sdrm_conn_hfuncs);
+
+       r = drm_connector_init(ddev, conn, &sdrm_conn_ops,
+                              DRM_MODE_CONNECTOR_VIRTUAL);
+       if (r < 0)
+               goto error;
+
+       r = drm_simple_display_pipe_init(ddev, &sdrm->pipe, &sdrm_pipe_funcs,
+                                        sdrm_formats,
+                                        ARRAY_SIZE(sdrm_formats), conn);
+       if (r < 0)
+               goto error;
+
+       drm_mode_config_reset(ddev);
+       return 0;
+
+error:
+       drm_mode_config_cleanup(ddev);
+       return r;
+}
+
+void sdrm_kms_unbind(struct sdrm_device *sdrm)
+{
+       if (sdrm->ddev->mode_config.funcs)
+               drm_mode_config_cleanup(sdrm->ddev);
+}
drivers/gpu/drm/simpledrm/simpledrm_of.c new file +49 -0
new file mode 100644
index 0000000..5620000
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2012-2016 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <drm/drmP.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include "simpledrm.h"
+
+#ifdef CONFIG_COMMON_CLK
+
+static int sdrm_of_bind_clocks(struct sdrm_device *sdrm,
+                              struct device_node *np)
+{
+       struct clk *clock;
+       size_t i, n;
+       int r;
+
+       n = of_clk_get_parent_count(np);
+       if (n < 1)
+               return 0;
+
+       sdrm->clks = kcalloc(n, sizeof(*sdrm->clks), GFP_KERNEL);
+       if (!sdrm->clks)
+               return -ENOMEM;
+
+       for (i = 0; i < n; ++i) {
+               clock = of_clk_get(np, i);
+               if (!IS_ERR(clock)) {
+                       sdrm->clks[sdrm->n_clks++] = clock;
+               } else if (PTR_ERR(clock) == -EPROBE_DEFER) {
+                       r = -EPROBE_DEFER;
+                       goto error;
+               } else {
+                       dev_err(sdrm->ddev->dev, "cannot find clock %zu: %ld\n",
+                               i, PTR_ERR(clock));
+               }

drivers/gpu/drm/simpledrm/simpledrm_of.c line 59

Quoted 10 lines
drivers/gpu/drm/simpledrm/simpledrm_of.c new file +10 -0
+       }
+
+       for (i = 0; i < sdrm->n_clks; ++i) {
+               if (!sdrm->clks[i])
+                       continue;
+
+               r = clk_prepare_enable(sdrm->clks[i]);
+               if (r < 0) {
+                       dev_err(sdrm->ddev->dev,
+                               "cannot find clock %zu: %d\n", i, r);

"cannot enable clock" ?

Quoted 209 lines
drivers/gpu/drm/simpledrm/simpledrm_of.c new file +206 -1
+                       clk_put(sdrm->clks[i]);
+                       sdrm->clks[i] = NULL;
+               }
+       }
+
+       return 0;
+
+error:
+       for (i = 0; i < sdrm->n_clks; ++i)
+               clk_put(sdrm->clks[i]);
+       kfree(sdrm->clks);
+       sdrm->clks = NULL;
+       sdrm->n_clks = 0;
+       return r;
+}
+
+static void sdrm_of_unbind_clocks(struct sdrm_device *sdrm)
+{
+       size_t i;
+
+       for (i = 0; i < sdrm->n_clks; ++i) {
+               clk_disable_unprepare(sdrm->clks[i]);
+               clk_put(sdrm->clks[i]);
+       }
+
+       kfree(sdrm->clks);
+       sdrm->clks = NULL;
+       sdrm->n_clks = 0;
+}
+
+#else /* CONFIG_COMMON_CLK */
+
+static int sdrm_of_bind_clocks(struct sdrm_device *sdrm,
+                              struct device_node *np)
+{
+       return 0;
+}
+
+static void sdrm_of_unbind_clocks(struct sdrm_device *sdrm)
+{
+}
+
+#endif /* CONFIG_COMMON_CLK */
+
+#ifdef CONFIG_REGULATOR
+
+static int sdrm_of_bind_regulators(struct sdrm_device *sdrm,
+                                  struct device_node *np)
+{
+       struct regulator *regulator;
+       struct property *prop;
+       char *p, *name;
+       size_t i, n;
+       int r;
+
+       n = 0;
+       for_each_property_of_node(np, prop) {
+               p = strstr(prop->name, "-supply");
+               if (p && p != prop->name)
+                       ++n;
+       }
+
+       if (n < 1)
+               return 0;
+
+       sdrm->regulators = kcalloc(n, sizeof(*sdrm->regulators), GFP_KERNEL);
+       if (!sdrm->regulators)
+               return -ENOMEM;
+
+       for_each_property_of_node(np, prop) {
+               p = strstr(prop->name, "-supply");
+               if (!p || p == prop->name)
+                       continue;
+
+               name = kstrndup(prop->name, p - prop->name, GFP_TEMPORARY);
+               if (!name)
+                       continue;
+
+               regulator = regulator_get_optional(sdrm->ddev->dev, name);
+               kfree(name);
+
+               if (!IS_ERR(regulator)) {
+                       sdrm->regulators[sdrm->n_regulators++] = regulator;
+               } else if (PTR_ERR(regulator) == -EPROBE_DEFER) {
+                       r = -EPROBE_DEFER;
+                       goto error;
+               } else {
+                       dev_warn(sdrm->ddev->dev,
+                                "cannot find regulator %s: %ld\n",
+                                prop->name, PTR_ERR(regulator));
+               }
+       }
+
+       for (i = 0; i < sdrm->n_regulators; ++i) {
+               if (!sdrm->regulators[i])
+                       continue;
+
+               r = regulator_enable(sdrm->regulators[i]);
+               if (r < 0) {
+                       dev_warn(sdrm->ddev->dev,
+                                "cannot enable regulator %zu: %d\n", i, r);
+                       regulator_put(sdrm->regulators[i]);
+                       sdrm->regulators[i] = NULL;
+               }
+       }
+
+       return 0;
+
+error:
+       for (i = 0; i < sdrm->n_regulators; ++i)
+               if (sdrm->regulators[i])
+                       regulator_put(sdrm->regulators[i]);
+       kfree(sdrm->regulators);
+       sdrm->regulators = NULL;
+       sdrm->n_regulators = 0;
+       return r;
+}
+
+static void sdrm_of_unbind_regulators(struct sdrm_device *sdrm)
+{
+       size_t i;
+
+       for (i = 0; i < sdrm->n_regulators; ++i) {
+               if (sdrm->regulators[i]) {
+                       regulator_disable(sdrm->regulators[i]);
+                       regulator_put(sdrm->regulators[i]);
+               }
+       }
+
+       kfree(sdrm->regulators);
+       sdrm->regulators = NULL;
+       sdrm->n_regulators = 0;
+}
+
+#else /* CONFIG_REGULATORS */
+
+static int sdrm_of_bind_regulators(struct sdrm_device *sdrm,
+                                  struct device_node *np)
+{
+       return 0;
+}
+
+static void sdrm_of_unbind_regulators(struct sdrm_device *sdrm)
+{
+}
+
+#endif /* CONFIG_REGULATORS */
+
+#ifdef CONFIG_OF
+
+void sdrm_of_bootstrap(void)
+{
+#ifdef CONFIG_OF_ADDRESS
+       struct device_node *np;
+
+       for_each_compatible_node(np, NULL, "simple-framebuffer")
+               of_platform_device_create(np, NULL, NULL);
+#endif
+}
+
+int sdrm_of_bind(struct sdrm_device *sdrm)
+{
+       int r;
+
+       if (WARN_ON(sdrm->n_clks > 0 || sdrm->n_regulators > 0))
+               return 0;
+       if (!sdrm->ddev->dev->of_node)
+               return 0;
+
+       r = sdrm_of_bind_clocks(sdrm, sdrm->ddev->dev->of_node);
+       if (r < 0)
+               goto error;
+
+       r = sdrm_of_bind_regulators(sdrm, sdrm->ddev->dev->of_node);
+       if (r < 0)
+               goto error;
+
+       return 0;
+
+error:
+       sdrm_of_unbind(sdrm);
+       return r;
+}
+
+void sdrm_of_unbind(struct sdrm_device *sdrm)
+{
+       sdrm_of_unbind_regulators(sdrm);
+       sdrm_of_unbind_clocks(sdrm);
+}
+
+#else /* CONFIG_OF */
+
+void sdrm_of_bootstrap(void)
+{
+}
+
+int sdrm_of_bind(struct sdrm_device *sdrm)
+{
+       return 0;
+}
+
+void sdrm_of_unbind(struct sdrm_device *sdrm)
+{
+}
+
+#endif /* CONFIG_OF */
--

2.9.3

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

#16 lore raw

Re: [PATCH v5 6/7] drm: add SimpleDRM driver

In reply to David Herrmann

Den 02.09.2016 10:22, skrev David Herrmann:

Quoted 12 lines

The SimpleDRM driver binds to simple-framebuffer devices and provides a DRM/KMS API. It provides only a single CRTC+encoder+connector combination plus one initial mode.

Userspace can create dumb-buffers which can be blit into the real framebuffer similar to UDL. No access to the real framebuffer is allowed (compared to earlier version of this driver) to avoid security issues. Furthermore, this way we can support arbitrary modes as long as we have a conversion-helper.

---

[...]

Quoted 1 line
drivers/gpu/drm/simpledrm/simpledrm_drv.c +0 -0

[...]

Quoted 13 lines
drivers/gpu/drm/simpledrm/simpledrm_drv.c +13 -0
+static int sdrm_fop_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct drm_file *dfile = file->private_data;
+	struct drm_device *dev = dfile->minor->dev;
+	struct drm_gem_object *obj = NULL;
+	struct drm_vma_offset_node *node;
+	int r;
+
+	drm_vma_offset_lock_lookup(dev->vma_offset_manager);
+	node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager,
+						  vma->vm_pgoff,
+						  vma_pages(vma));
+	if (likely(node)) {

drivers/gpu/drm/simpledrm/simpledrm_drv.c line 308

Quoted 10 lines
drivers/gpu/drm/simpledrm/simpledrm_drv.c +10 -0
+		obj = container_of(node, struct drm_gem_object, vma_node);
+		if (!kref_get_unless_zero(&obj->refcount))
+			obj = NULL;
+	}
+	drm_vma_offset_unlock_lookup(dev->vma_offset_manager);
+
+	if (!obj)
+		return -EINVAL;
+
+	if (!drm_vma_node_is_allowed(node, dfile)) {

I get:
drivers/gpu/drm/simpledrm/simpledrm_drv.c:320:2: warning: passing argument 2 of ‘drm_vma_node_is_allowed’ from incompatible pointer type [enabled by default]

dfile -> file

Quoted 13 lines
drivers/gpu/drm/simpledrm/simpledrm_drv.c +13 -0
+		drm_gem_object_unreference_unlocked(obj);
+		return -EACCES;
+	}
+
+	if (vma->vm_file)
+		fput(vma->vm_file);
+	vma->vm_file = get_file(obj->filp);
+	vma->vm_pgoff = 0;
+
+	r = obj->filp->f_op->mmap(obj->filp, vma);
+	drm_gem_object_unreference_unlocked(obj);
+	return r;
+}

[...]

Quoted 1 line
drivers/gpu/drm/simpledrm/simpledrm_kms.c +0 -0

[...]

Quoted 31 lines
drivers/gpu/drm/simpledrm/simpledrm_kms.c +31 -0
+static void sdrm_crtc_send_vblank_event(struct drm_crtc *crtc)
+{
+	if (crtc->state && crtc->state->event) {
+		spin_lock_irq(&crtc->dev->event_lock);
+		drm_crtc_send_vblank_event(crtc, crtc->state->event);
+		spin_unlock_irq(&crtc->dev->event_lock);
+		crtc->state->event = NULL;
+	}
+}
+
+void sdrm_display_pipe_update(struct drm_simple_display_pipe *pipe,
+			      struct drm_plane_state *plane_state)
+{
+	struct drm_framebuffer *dfb = pipe->plane.state->fb;
+	struct sdrm_fb *fb;
+
+	sdrm_crtc_send_vblank_event(&pipe->crtc);
+
+	if (dfb) {
+		fb = container_of(dfb, struct sdrm_fb, base);
+		pipe->plane.fb = dfb;
+		sdrm_dirty(fb, 0, 0, dfb->width, dfb->height);
+	}
+}
+
+static void sdrm_display_pipe_enable(struct drm_simple_display_pipe *pipe,
+				     struct drm_crtc_state *crtc_state)
+{
+	sdrm_crtc_send_vblank_event(&pipe->crtc);
+}
+

drivers/gpu/drm/simpledrm/simpledrm_kms.c line 112

Quoted 10 lines
drivers/gpu/drm/simpledrm/simpledrm_kms.c +10 -0
+static void sdrm_display_pipe_disable(struct drm_simple_display_pipe *pipe)
+{
+	sdrm_crtc_send_vblank_event(&pipe->crtc);
+}
+
+static const struct drm_simple_display_pipe_funcs sdrm_pipe_funcs = {
+	.update		= sdrm_display_pipe_update,
+	.enable		= sdrm_display_pipe_enable,
+	.disable	= sdrm_display_pipe_disable,
+};

The enable and disable callbacks can be removed. This commit in drm-misc fixed the flip done timeout:
drm/simple-helpers: Always add planes to the state update

Noralf.

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#17 lore raw

Re: [PATCH v5 6/7] drm: add SimpleDRM driver

Hey

Quoted 55 lines · Noralf Trønnes

Den 02.09.2016 10:22, skrev David Herrmann:

Quoted 13 lines

The SimpleDRM driver binds to simple-framebuffer devices and provides a DRM/KMS API. It provides only a single CRTC+encoder+connector combination plus one initial mode.

Userspace can create dumb-buffers which can be blit into the real framebuffer similar to UDL. No access to the real framebuffer is allowed (compared to earlier version of this driver) to avoid security issues. Furthermore, this way we can support arbitrary modes as long as we have a conversion-helper.

---

[...]

Quoted 2 lines
drivers/gpu/drm/simpledrm/simpledrm_drv.c +0 -0

[...]

Quoted 13 lines
drivers/gpu/drm/simpledrm/simpledrm_drv.c +13 -0
+static int sdrm_fop_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct drm_file *dfile = file->private_data;
+       struct drm_device *dev = dfile->minor->dev;
+       struct drm_gem_object *obj = NULL;
+       struct drm_vma_offset_node *node;
+       int r;
+
+       drm_vma_offset_lock_lookup(dev->vma_offset_manager);
+       node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager,
+                                                 vma->vm_pgoff,
+                                                 vma_pages(vma));
+       if (likely(node)) {

drivers/gpu/drm/simpledrm/simpledrm_drv.c line 308

Quoted 10 lines
drivers/gpu/drm/simpledrm/simpledrm_drv.c +10 -0
+               obj = container_of(node, struct drm_gem_object, vma_node);
+               if (!kref_get_unless_zero(&obj->refcount))
+                       obj = NULL;
+       }
+       drm_vma_offset_unlock_lookup(dev->vma_offset_manager);
+
+       if (!obj)
+               return -EINVAL;
+
+       if (!drm_vma_node_is_allowed(node, dfile)) {

I get:
drivers/gpu/drm/simpledrm/simpledrm_drv.c:320:2: warning: passing argument 2 of ‘drm_vma_node_is_allowed’ from incompatible pointer type [enabled by default]

Quoted 1 line

dfile -> file

Yeah, either change that, or apply "[PATCH 0/6] DRM Core Cleanups" before. I suspect the cleanups to go in before this driver, so didn't bother changing it.

Quoted 64 lines
Quoted 13 lines
drivers/gpu/drm/simpledrm/simpledrm_drv.c +13 -0
+               drm_gem_object_unreference_unlocked(obj);
+               return -EACCES;
+       }
+
+       if (vma->vm_file)
+               fput(vma->vm_file);
+       vma->vm_file = get_file(obj->filp);
+       vma->vm_pgoff = 0;
+
+       r = obj->filp->f_op->mmap(obj->filp, vma);
+       drm_gem_object_unreference_unlocked(obj);
+       return r;
+}

[...]

Quoted 2 lines
drivers/gpu/drm/simpledrm/simpledrm_kms.c +0 -0

[...]

Quoted 40 lines
drivers/gpu/drm/simpledrm/simpledrm_kms.c +26 -0
+static void sdrm_crtc_send_vblank_event(struct drm_crtc *crtc)
+{
+       if (crtc->state && crtc->state->event) {
+               spin_lock_irq(&crtc->dev->event_lock);
+               drm_crtc_send_vblank_event(crtc, crtc->state->event);
+               spin_unlock_irq(&crtc->dev->event_lock);
+               crtc->state->event = NULL;
+       }
+}
+
+void sdrm_display_pipe_update(struct drm_simple_display_pipe *pipe,
+                             struct drm_plane_state *plane_state)
+{
+       struct drm_framebuffer *dfb = pipe->plane.state->fb;
+       struct sdrm_fb *fb;
+
+       sdrm_crtc_send_vblank_event(&pipe->crtc);
+
+       if (dfb) {
+               fb = container_of(dfb, struct sdrm_fb, base);
+               pipe->plane.fb = dfb;
+               sdrm_dirty(fb, 0, 0, dfb->width, dfb->height);
+       }
+}
+
+static void sdrm_display_pipe_enable(struct drm_simple_display_pipe

*pipe,

drivers/gpu/drm/simpledrm/simpledrm_kms.c +6 -0
+                                    struct drm_crtc_state *crtc_state)
+{
+       sdrm_crtc_send_vblank_event(&pipe->crtc);
+}
+
+static void sdrm_display_pipe_disable(struct drm_simple_display_pipe

*pipe)

drivers/gpu/drm/simpledrm/simpledrm_kms.c +6 -0
+{
+       sdrm_crtc_send_vblank_event(&pipe->crtc);
+}
+
+static const struct drm_simple_display_pipe_funcs sdrm_pipe_funcs = {
+       .update         = sdrm_display_pipe_update,
Quoted 8 lines

drivers/gpu/drm/simpledrm/simpledrm_kms.c line 112

Quoted 3 lines
drivers/gpu/drm/simpledrm/simpledrm_kms.c +3 -0
+       .enable         = sdrm_display_pipe_enable,
+       .disable        = sdrm_display_pipe_disable,
+};

The enable and disable callbacks can be removed. This commit in drm-misc fixed the flip done timeout:
drm/simple-helpers: Always add planes to the state update

Right, Daniel told me on IRC already. With this fix applied, I can run Xorg on top of it just fine.

I dropped the enable/disable callbacks as well now.

Thanks
David
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#18 lore raw

Re: [PATCH v5 6/7] drm: add SimpleDRM driver

In reply to David Herrmann

Den 02.09.2016 10:22, skrev David Herrmann:

Quoted 12 lines

The SimpleDRM driver binds to simple-framebuffer devices and provides a DRM/KMS API. It provides only a single CRTC+encoder+connector combination plus one initial mode.

Userspace can create dumb-buffers which can be blit into the real framebuffer similar to UDL. No access to the real framebuffer is allowed (compared to earlier version of this driver) to avoid security issues. Furthermore, this way we can support arbitrary modes as long as we have a conversion-helper.

---

[...]

Quoted 391 lines
drivers/gpu/drm/simpledrm/simpledrm_drv.c new file +385 -0
new file mode 100644
index 0000000..d569120
@@ -0,0 +1,464 @@
+/*
+ * Copyright (C) 2012-2016 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <drm/drmP.h>
+#include <linux/atomic.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_data/simplefb.h>
+#include <linux/string.h>
+#include "simpledrm.h"
+
+static struct drm_driver sdrm_drm_driver;
+static DEFINE_MUTEX(sdrm_lock);
+
+static int sdrm_hw_identify(struct platform_device *pdev,
+			    struct simplefb_platform_data *modep,
+			    struct simplefb_format *formatp,
+			    struct resource **memp,
+			    u32 *bppp)
+{
+	static const struct simplefb_format valid_formats[] = SIMPLEFB_FORMATS;
+	struct simplefb_platform_data pm = {}, *mode = pdev->dev.platform_data;
+	struct device_node *np = pdev->dev.of_node;
+	const struct simplefb_format *format = NULL;
+	struct resource *mem;
+	unsigned int depth;
+	int r, bpp;
+	size_t i;
+
+	if (!mode) {
+		if (!np)
+			return -ENODEV;
+
+		mode = &pm;
+
+		r = of_property_read_u32(np, "width", &mode->width);
+		if (r >= 0)
+			r = of_property_read_u32(np, "height", &mode->height);
+		if (r >= 0)
+			r = of_property_read_u32(np, "stride", &mode->stride);
+		if (r >= 0)
+			r = of_property_read_string(np, "format",
+						    &mode->format);
+		if (r < 0)
+			return r;
+	}
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem)
+		return -ENODEV;
+
+	for (i = 0; i < ARRAY_SIZE(valid_formats); ++i) {
+		if (!strcmp(mode->format, valid_formats[i].name)) {
+			format = &valid_formats[i];
+			break;
+		}
+	}
+
+	if (!format)
+		return -ENODEV;
+
+	switch (format->fourcc) {
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_XRGB1555:
+	case DRM_FORMAT_ARGB1555:
+	case DRM_FORMAT_RGB888:
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_XRGB2101010:
+	case DRM_FORMAT_ARGB2101010:
+		/*
+		 * You must adjust sdrm_put() whenever you add a new format
+		 * here, otherwise, blitting operations will not work.
+		 * Furthermore, include/linux/platform_data/simplefb.h needs
+		 * to be adjusted so the platform-device actually allows this
+		 * format.
+		 */
+		break;
+	default:
+		return -ENODEV;
+	}
+
+	drm_fb_get_bpp_depth(format->fourcc, &depth, &bpp);
+	if (!bpp)
+		return -ENODEV;
+	if (resource_size(mem) < mode->stride * mode->height)
+		return -ENODEV;
+	if ((bpp + 7) / 8 * mode->width > mode->stride)
+		return -ENODEV;
+
+	*modep = *mode;
+	*formatp = *format;
+	*memp = mem;
+	*bppp = bpp;
+	return 0;
+}
+
+static struct sdrm_hw *sdrm_hw_new(const struct simplefb_platform_data *mode,
+				   const struct simplefb_format *format,
+				   const struct resource *mem,
+				   u32 bpp)
+{
+	struct sdrm_hw *hw;
+
+	hw = kzalloc(sizeof(*hw), GFP_KERNEL);
+	if (!hw)
+		return ERR_PTR(-ENOMEM);
+
+	mutex_init(&hw->lock);
+	hw->width = mode->width;
+	hw->height = mode->height;
+	hw->stride = mode->stride;
+	hw->bpp = bpp;
+	hw->format = format->fourcc;
+	hw->base = mem->start;
+	hw->size = resource_size(mem);
+
+	return hw;
+}
+
+static struct sdrm_hw *sdrm_hw_free(struct sdrm_hw *hw)
+{
+	if (!hw)
+		return NULL;
+
+	WARN_ON(hw->map);
+	mutex_destroy(&hw->lock);
+	kfree(hw);
+
+	return NULL;
+}
+
+static int sdrm_hw_bind(struct sdrm_hw *hw)
+{
+	mutex_lock(&hw->lock);
+	if (!hw->map)
+		hw->map = ioremap_wc(hw->base, hw->size);
+	mutex_unlock(&hw->lock);
+
+	return hw->map ? 0 : -EIO;
+}
+
+static void sdrm_hw_unbind(struct sdrm_hw *hw)
+{
+	if (!hw)
+		return;
+
+	mutex_lock(&hw->lock);
+	if (hw->map) {
+		iounmap(hw->map);
+		hw->map = NULL;
+	}
+	mutex_unlock(&hw->lock);
+}
+
+static struct sdrm_device *sdrm_device_free(struct sdrm_device *sdrm)
+{
+	if (!sdrm)
+		return NULL;
+
+	WARN_ON(atomic_read(&sdrm->n_used) != INT_MIN);
+	sdrm->hw = sdrm_hw_free(sdrm->hw);
+	drm_dev_unref(sdrm->ddev);
+	kfree(sdrm);
+
+	return NULL;
+}
+
+static struct sdrm_device *sdrm_device_new(struct platform_device *pdev,
+					   struct sdrm_hw *hw)
+{
+	struct sdrm_device *sdrm;
+	int r;
+
+	sdrm = kzalloc(sizeof(*sdrm), GFP_KERNEL);
+	if (!sdrm)
+		return ERR_PTR(-ENOMEM);
+
+	atomic_set(&sdrm->n_used, INT_MIN);
+
+	sdrm->ddev = drm_dev_alloc(&sdrm_drm_driver, &pdev->dev);
+	if (!sdrm->ddev) {
+		r = -ENOMEM;
+		goto error;
+	}
+
+	sdrm->ddev->dev_private = sdrm;
+	sdrm->hw = hw;
+
+	return sdrm;
+
+error:
+	sdrm_device_free(sdrm);
+	return ERR_PTR(r);
+}
+
+static void sdrm_device_unbind(struct sdrm_device *sdrm)
+{
+	if (sdrm) {
+		sdrm_kms_unbind(sdrm);
+		sdrm_hw_unbind(sdrm->hw);
+		sdrm_of_unbind(sdrm);
+	}
+}
+
+static int sdrm_device_bind(struct sdrm_device *sdrm)
+{
+	int r;
+
+	r = sdrm_of_bind(sdrm);
+	if (r < 0)
+		goto error;
+
+	r = sdrm_hw_bind(sdrm->hw);
+	if (r < 0)
+		goto error;
+
+	r = sdrm_kms_bind(sdrm);
+	if (r < 0)
+		goto error;
+
+	return 0;
+
+error:
+	sdrm_device_unbind(sdrm);
+	return r;
+}
+
+static int sdrm_device_acquire(struct sdrm_device *sdrm)
+{
+	return (sdrm && atomic_inc_unless_negative(&sdrm->n_used))
+		? 0 : -ENODEV;
+}
+
+static void sdrm_device_release(struct sdrm_device *sdrm)
+{
+	if (sdrm && atomic_dec_return(&sdrm->n_used) == INT_MIN) {
+		sdrm_device_unbind(sdrm);
+		sdrm_device_free(sdrm);
+	}
+}
+
+static int sdrm_fop_open(struct inode *inode, struct file *file)
+{
+	struct drm_device *ddev;
+	int r;
+
+	mutex_lock(&sdrm_lock);
+	r = drm_open(inode, file);
+	if (r >= 0) {
+		ddev = file->private_data;
+		r = sdrm_device_acquire(ddev->dev_private);
+		if (r < 0)
+			drm_release(inode, file);
+	}
+	mutex_unlock(&sdrm_lock);
+
+	return r;
+}
+
+static int sdrm_fop_release(struct inode *inode, struct file *file)
+{
+	struct drm_file *dfile = file->private_data;
+	struct drm_device *ddev = dfile->minor->dev;
+	struct sdrm_device *sdrm = ddev->dev_private;
+	int res;
+
+	res = drm_release(inode, file);
+	sdrm_device_release(sdrm);
+	return res;
+}
+
+static int sdrm_fop_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct drm_file *dfile = file->private_data;
+	struct drm_device *dev = dfile->minor->dev;
+	struct drm_gem_object *obj = NULL;
+	struct drm_vma_offset_node *node;
+	int r;
+
+	drm_vma_offset_lock_lookup(dev->vma_offset_manager);
+	node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager,
+						  vma->vm_pgoff,
+						  vma_pages(vma));
+	if (likely(node)) {
+		obj = container_of(node, struct drm_gem_object, vma_node);
+		if (!kref_get_unless_zero(&obj->refcount))
+			obj = NULL;
+	}
+	drm_vma_offset_unlock_lookup(dev->vma_offset_manager);
+
+	if (!obj)
+		return -EINVAL;
+
+	if (!drm_vma_node_is_allowed(node, dfile)) {
+		drm_gem_object_unreference_unlocked(obj);
+		return -EACCES;
+	}
+
+	if (vma->vm_file)
+		fput(vma->vm_file);
+	vma->vm_file = get_file(obj->filp);
+	vma->vm_pgoff = 0;
+
+	r = obj->filp->f_op->mmap(obj->filp, vma);
+	drm_gem_object_unreference_unlocked(obj);
+	return r;
+}
+
+static int sdrm_simplefb_probe(struct platform_device *pdev)
+{
+	struct simplefb_platform_data hw_mode;
+	struct simplefb_format hw_format;
+	struct sdrm_device *sdrm = NULL;
+	struct sdrm_hw *hw = NULL;
+	struct resource *hw_mem;
+	u32 hw_bpp;
+	int r;
+
+	r = sdrm_hw_identify(pdev, &hw_mode, &hw_format, &hw_mem, &hw_bpp);
+	if (r < 0)
+		goto error;
+
+	hw = sdrm_hw_new(&hw_mode, &hw_format, hw_mem, hw_bpp);
+	if (IS_ERR(hw)) {
+		r = PTR_ERR(hw);
+		hw = NULL;
+		goto error;
+	}
+
+	sdrm = sdrm_device_new(pdev, hw);
+	if (IS_ERR(sdrm)) {
+		r = PTR_ERR(sdrm);
+		sdrm = NULL;
+		goto error;
+	}
+	hw = NULL;
+	platform_set_drvdata(pdev, sdrm);
+
+	r = sdrm_device_bind(sdrm);
+	if (r < 0)
+		goto error;
+
+	/* mark device as enabled and acquire bus ref */
+	WARN_ON(atomic_read(&sdrm->n_used) != INT_MIN);
+	atomic_set(&sdrm->n_used, 1);
+
+	r = drm_dev_register(sdrm->ddev, 0);
+	if (r < 0) {
+		/* mark device as disabled and drop bus ref */
+		WARN_ON(atomic_add_return(INT_MIN, &sdrm->n_used) != INT_MIN);
+		sdrm_device_release(sdrm);
+		return r;
+	}
+
+	dev_info(sdrm->ddev->dev, "initialized %s on minor %d\n",
+		 sdrm->ddev->driver->name, sdrm->ddev->primary->index);
+
+	return 0;
+
+error:
+	sdrm_device_unbind(sdrm);
+	sdrm_device_free(sdrm);
+	sdrm_hw_free(hw);
+	return r;
+}
+
+static int sdrm_simplefb_remove(struct platform_device *pdev)
+{
+	struct sdrm_device *sdrm = platform_get_drvdata(pdev);
+
+	/* mark device as disabled */

drivers/gpu/drm/simpledrm/simpledrm_drv.c line 395

Quoted 10 lines
drivers/gpu/drm/simpledrm/simpledrm_drv.c new file +10 -0
+	atomic_add(INT_MIN, &sdrm->n_used);
+	sdrm_hw_unbind(sdrm->hw);
+
+	mutex_lock(&sdrm_lock);
+	drm_dev_unregister(sdrm->ddev);
+	sdrm_device_release(sdrm);
+	mutex_unlock(&sdrm_lock);
+
+	return 0;
+}

There is something wrong with the ref counting.
Load, unload is fine:

$ sudo modprobe simpledrm
$ echo 0 | sudo tee /sys/class/vtconsole/vtcon1/bind
$ sudo modprobe -r simpledrm
$ ls -l /dev/fb*
ls: cannot access /dev/fb*: No such file or directory

But if I run modetest in between it's not released:

$ sudo modprobe simpledrm
$ ./libdrm/tests/modetest/modetest -M "simpledrm" -s 23:1824x984
setting mode 1824x984-60Hz@XR24 on connectors 23, crtc 25
$ echo 0 | sudo tee /sys/class/vtconsole/vtcon1/bind
$ sudo modprobe -r simpledrm
$ ls -l /dev/fb*
crw-rw---- 1 root video 29, 0 Sep  5 15:43 /dev/fb0

Noralf.

Quoted 60 lines
drivers/gpu/drm/simpledrm/simpledrm_drv.c new file +59 -0
+
+static const struct file_operations sdrm_drm_fops = {
+	.owner = THIS_MODULE,
+	.open = sdrm_fop_open,
+	.release = sdrm_fop_release,
+	.mmap = sdrm_fop_mmap,
+	.poll = drm_poll,
+	.read = drm_read,
+	.unlocked_ioctl = drm_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = drm_compat_ioctl,
+#endif
+	.llseek = noop_llseek,
+};
+
+static struct drm_driver sdrm_drm_driver = {
+	.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
+	.fops = &sdrm_drm_fops,
+
+	.gem_free_object = sdrm_bo_free,
+
+	.dumb_create = sdrm_dumb_create,
+	.dumb_map_offset = sdrm_dumb_map_offset,
+	.dumb_destroy = drm_gem_dumb_destroy,
+
+	.name = "simpledrm",
+	.desc = "Simple firmware framebuffer DRM driver",
+	.date = "20160901",
+};
+
+static const struct of_device_id sdrm_simplefb_of_match[] = {
+	{ .compatible = "simple-framebuffer", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, sdrm_simplefb_of_match);
+
+static struct platform_driver sdrm_simplefb_driver = {
+	.probe = sdrm_simplefb_probe,
+	.remove = sdrm_simplefb_remove,
+	.driver = {
+		.name = "simple-framebuffer",
+		.mod_name = KBUILD_MODNAME,
+		.owner = THIS_MODULE,
+		.of_match_table = sdrm_simplefb_of_match,
+	},
+};
+
+static int __init sdrm_init(void)
+{
+	int r;
+
+	r = platform_driver_register(&sdrm_simplefb_driver);
+	if (r < 0)
+		return r;
+
+	sdrm_of_bootstrap();
+	return 0;
+}
+

drivers/gpu/drm/simpledrm/simpledrm_drv.c line 464

Quoted 10 lines
drivers/gpu/drm/simpledrm/simpledrm_drv.c new file +10 -0
+static void __exit sdrm_exit(void)
+{
+	platform_driver_unregister(&sdrm_simplefb_driver);
+}
+
+module_init(sdrm_init);
+module_exit(sdrm_exit);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Simple firmware framebuffer DRM driver");
+MODULE_ALIAS("platform:simple-framebuffer");

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#19 lore raw

PATCH v5 7/7 drm/simpledrm: add fbdev fallback support

In reply to David Herrmann

Create a simple fbdev device during SimpleDRM setup so legacy user-space and fbcon can use it.

---
 drivers/gpu/drm/simpledrm/Makefile          |   1 +
 drivers/gpu/drm/simpledrm/simpledrm.h       |   8 ++
 drivers/gpu/drm/simpledrm/simpledrm_drv.c   |  13 +++
 drivers/gpu/drm/simpledrm/simpledrm_fbdev.c | 143 ++++++++++++++++++++++++++++
 drivers/gpu/drm/simpledrm/simpledrm_kms.c   |  55 ++++++-----
 5 files changed, 196 insertions(+), 24 deletions(-)
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_fbdev.c
drivers/gpu/drm/simpledrm/Makefile +1 -0
index d7b179d..e368d14 100644
@@ -1,6 +1,7 @@
 simpledrm-y := \
 	simpledrm_damage.o \
 	simpledrm_drv.o \
+	simpledrm_fbdev.o \
 	simpledrm_gem.o \
 	simpledrm_kms.o \
 	simpledrm_of.o
drivers/gpu/drm/simpledrm/simpledrm.h +8 -0
index ed6d725..d7a2045 100644
@@ -19,6 +19,7 @@
 #include <linux/mutex.h>
 
 struct clk;
+struct drm_fb_helper;
 struct regulator;
 struct simplefb_format;
 
@@ -49,6 +50,7 @@ struct sdrm_device {
 	atomic_t n_used;
 	struct drm_device *ddev;
 	struct sdrm_hw *hw;
+	struct drm_fb_helper *fbdev;
 
 	size_t n_clks;
 	size_t n_regulators;
@@ -66,6 +68,9 @@ void sdrm_of_unbind(struct sdrm_device *sdrm);
 int sdrm_kms_bind(struct sdrm_device *sdrm);
 void sdrm_kms_unbind(struct sdrm_device *sdrm);
 
+void sdrm_fbdev_bind(struct sdrm_device *sdrm);
+void sdrm_fbdev_unbind(struct sdrm_device *sdrm);
+
 void sdrm_dirty(struct sdrm_fb *fb, u32 x, u32 y, u32 width, u32 height);
 
 struct sdrm_bo *sdrm_bo_new(struct drm_device *ddev, size_t size);
@@ -80,4 +85,7 @@ int sdrm_dumb_map_offset(struct drm_file *dfile,
 			 uint32_t handle,
 			 uint64_t *offset);
 
+struct sdrm_fb *sdrm_fb_new(struct sdrm_bo *bo,
+			    const struct drm_mode_fb_cmd2 *cmd);
+
 #endif /* __SDRM_SIMPLEDRM_H */
drivers/gpu/drm/simpledrm/simpledrm_drv.c +13 -0
index d569120..6aefe49 100644
@@ -9,6 +9,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
 #include <linux/atomic.h>
 #include <linux/err.h>
 #include <linux/io.h>
@@ -210,6 +211,7 @@ error:
 static void sdrm_device_unbind(struct sdrm_device *sdrm)
 {
 	if (sdrm) {
+		sdrm_fbdev_unbind(sdrm);
 		sdrm_kms_unbind(sdrm);
 		sdrm_hw_unbind(sdrm->hw);
 		sdrm_of_unbind(sdrm);
@@ -232,6 +234,8 @@ static int sdrm_device_bind(struct sdrm_device *sdrm)
 	if (r < 0)
 		goto error;
 
+	sdrm_fbdev_bind(sdrm);
+
 	return 0;
 
 error:
@@ -253,6 +257,14 @@ static void sdrm_device_release(struct sdrm_device *sdrm)
 	}
 }
 
+static void sdrm_device_lastclose(struct drm_device *ddev)
+{
+	struct sdrm_device *sdrm = ddev->dev_private;
+
+	if (sdrm->fbdev)
+		drm_fb_helper_restore_fbdev_mode_unlocked(sdrm->fbdev);
+}
+
 static int sdrm_fop_open(struct inode *inode, struct file *file)
 {
 	struct drm_device *ddev;
@@ -411,6 +423,7 @@ static const struct file_operations sdrm_drm_fops = {
 static struct drm_driver sdrm_drm_driver = {
 	.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
 	.fops = &sdrm_drm_fops,
+	.lastclose = sdrm_device_lastclose,
 
 	.gem_free_object = sdrm_bo_free,
 
drivers/gpu/drm/simpledrm/simpledrm_fbdev.c new file +143 -0

143 lines not on this page · raw message

drivers/gpu/drm/simpledrm/simpledrm_kms.c +31 -24

84 lines not on this page · raw message

Signature · 6 lines
2.9.3

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
#20 lore raw

Re: [PATCH v5 7/7] drm/simpledrm: add fbdev fallback support

Den 02.09.2016 10:22, skrev David Herrmann:

Quoted 4 lines

Create a simple fbdev device during SimpleDRM setup so legacy user-space and fbcon can use it.

[...]

Quoted 1 line
drivers/gpu/drm/simpledrm/simpledrm_fbdev.c +0 -0

[...]

Quoted 37 lines
drivers/gpu/drm/simpledrm/simpledrm_fbdev.c +37 -0
+void sdrm_fbdev_bind(struct sdrm_device *sdrm)
+{
+	struct drm_fb_helper *fbdev;
+	int r;
+
+	fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
+	if (!fbdev)
+		return;
+
+	drm_fb_helper_prepare(sdrm->ddev, fbdev, &sdrm_fbdev_funcs);
+
+	r = drm_fb_helper_init(sdrm->ddev, fbdev, 1, 1);
+	if (r < 0)
+		goto error;
+
+	r = drm_fb_helper_single_add_all_connectors(fbdev);
+	if (r < 0)
+		goto error;
+
+	r = drm_fb_helper_initial_config(fbdev,
+				sdrm->ddev->mode_config.preferred_depth);
+	if (r < 0)
+		goto error;
+
+	if (!fbdev->fbdev)
+		goto error;
+
+	sdrm->fbdev = fbdev;
+	return;
+
+error:
+	drm_fb_helper_fini(fbdev);
+	kfree(fbdev);
+}
+
+void sdrm_fbdev_unbind(struct sdrm_device *sdrm)
+{

drivers/gpu/drm/simpledrm/simpledrm_fbdev.c line 139

Quoted 10 lines
drivers/gpu/drm/simpledrm/simpledrm_fbdev.c +10 -0
+	struct drm_fb_helper *fbdev = sdrm->fbdev;
+
+	if (!fbdev)
+		return;
+
+	sdrm->fbdev = NULL;
+	drm_fb_helper_unregister_fbi(fbdev);
+	cancel_work_sync(&fbdev->dirty_work);
+	drm_fb_helper_release_fbi(fbdev);
+	drm_framebuffer_unreference(fbdev->fb);

I get a warning that there are still fb's left during unbind:

[   48.666003] WARNING: CPU: 0 PID: 716 at drivers/gpu/drm/drm_crtc.c:3855 drm_mode_config_cleanup+0x180/0x1f4 [drm]

This worked:

-       drm_framebuffer_unreference(fbdev->fb);
+       drm_framebuffer_unregister_private(fbdev->fb);
+       drm_framebuffer_cleanup(fbdev->fb);

Noralf.

drivers/gpu/drm/simpledrm/simpledrm_fbdev.c line 143

Quoted 4 lines
drivers/gpu/drm/simpledrm/simpledrm_fbdev.c +4 -0
+	fbdev->fb = NULL;
+	drm_fb_helper_fini(fbdev);
+	kfree(fbdev);
+}

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#21 lore raw

Re: [PATCH v5 7/7] drm/simpledrm: add fbdev fallback support

Den 03.09.2016 14:04, skrev Noralf Trønnes:

Quoted 68 lines

Den 02.09.2016 10:22, skrev David Herrmann:

Quoted 4 lines

Create a simple fbdev device during SimpleDRM setup so legacy user-space and fbcon can use it.

[...]

Quoted 1 line
drivers/gpu/drm/simpledrm/simpledrm_fbdev.c +0 -0

[...]

Quoted 37 lines
drivers/gpu/drm/simpledrm/simpledrm_fbdev.c +37 -0
+void sdrm_fbdev_bind(struct sdrm_device *sdrm)
+{
+    struct drm_fb_helper *fbdev;
+    int r;
+
+    fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
+    if (!fbdev)
+        return;
+
+    drm_fb_helper_prepare(sdrm->ddev, fbdev, &sdrm_fbdev_funcs);
+
+    r = drm_fb_helper_init(sdrm->ddev, fbdev, 1, 1);
+    if (r < 0)
+        goto error;
+
+    r = drm_fb_helper_single_add_all_connectors(fbdev);
+    if (r < 0)
+        goto error;
+
+    r = drm_fb_helper_initial_config(fbdev,
+                sdrm->ddev->mode_config.preferred_depth);
+    if (r < 0)
+        goto error;
+
+    if (!fbdev->fbdev)
+        goto error;
+
+    sdrm->fbdev = fbdev;
+    return;
+
+error:
+    drm_fb_helper_fini(fbdev);
+    kfree(fbdev);
+}
+
+void sdrm_fbdev_unbind(struct sdrm_device *sdrm)
+{

drivers/gpu/drm/simpledrm/simpledrm_fbdev.c line 139

Quoted 10 lines
drivers/gpu/drm/simpledrm/simpledrm_fbdev.c +10 -0
+    struct drm_fb_helper *fbdev = sdrm->fbdev;
+
+    if (!fbdev)
+        return;
+
+    sdrm->fbdev = NULL;
+    drm_fb_helper_unregister_fbi(fbdev);
+    cancel_work_sync(&fbdev->dirty_work);
+    drm_fb_helper_release_fbi(fbdev);
+    drm_framebuffer_unreference(fbdev->fb);

I get a warning that there are still fb's left during unbind:

[   48.666003] WARNING: CPU: 0 PID: 716 at drivers/gpu/drm/drm_crtc.c:3855 drm_mode_config_cleanup+0x180/0x1f4 [drm]

This worked:

Review

Quoted 3 lines
(quoted diff) +2 -1
-       drm_framebuffer_unreference(fbdev->fb);
+       drm_framebuffer_unregister_private(fbdev->fb);
+       drm_framebuffer_cleanup(fbdev->fb);

Well not quite, this doesn't free the bo, so maybe this:

-       drm_framebuffer_unreference(fbdev->fb);
+       drm_framebuffer_unregister_private(fbdev->fb);
+       sdrm_fb_destroy(fbdev->fb);

IIRC the reason ref count doesn't drop to zero, had something to do with multiple fb_set_par calls taking reference but not being dropped later.

Noralf.

Quoted 8 lines

Noralf.

drivers/gpu/drm/simpledrm/simpledrm_fbdev.c line 143

Quoted 4 lines
drivers/gpu/drm/simpledrm/simpledrm_fbdev.c +4 -0
+    fbdev->fb = NULL;
+    drm_fb_helper_fini(fbdev);
+    kfree(fbdev);
+}
Quoted 5 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

#22 lore raw

Re: [PATCH v5 7/7] drm/simpledrm: add fbdev fallback support

Hi

Quoted 87 lines · Noralf Trønnes

Den 03.09.2016 14:04, skrev Noralf Trønnes:

Quoted 75 lines

Den 02.09.2016 10:22, skrev David Herrmann:

Quoted 5 lines

Create a simple fbdev device during SimpleDRM setup so legacy user-space and fbcon can use it.

[...]

Quoted 2 lines
drivers/gpu/drm/simpledrm/simpledrm_fbdev.c +0 -0

[...]

Quoted 37 lines
drivers/gpu/drm/simpledrm/simpledrm_fbdev.c +37 -0
+void sdrm_fbdev_bind(struct sdrm_device *sdrm)
+{
+    struct drm_fb_helper *fbdev;
+    int r;
+
+    fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
+    if (!fbdev)
+        return;
+
+    drm_fb_helper_prepare(sdrm->ddev, fbdev, &sdrm_fbdev_funcs);
+
+    r = drm_fb_helper_init(sdrm->ddev, fbdev, 1, 1);
+    if (r < 0)
+        goto error;
+
+    r = drm_fb_helper_single_add_all_connectors(fbdev);
+    if (r < 0)
+        goto error;
+
+    r = drm_fb_helper_initial_config(fbdev,
+                sdrm->ddev->mode_config.preferred_depth);
+    if (r < 0)
+        goto error;
+
+    if (!fbdev->fbdev)
+        goto error;
+
+    sdrm->fbdev = fbdev;
+    return;
+
+error:
+    drm_fb_helper_fini(fbdev);
+    kfree(fbdev);
+}
+
+void sdrm_fbdev_unbind(struct sdrm_device *sdrm)
+{

drivers/gpu/drm/simpledrm/simpledrm_fbdev.c line 139

Quoted 10 lines
drivers/gpu/drm/simpledrm/simpledrm_fbdev.c +10 -0
+    struct drm_fb_helper *fbdev = sdrm->fbdev;
+
+    if (!fbdev)
+        return;
+
+    sdrm->fbdev = NULL;
+    drm_fb_helper_unregister_fbi(fbdev);
+    cancel_work_sync(&fbdev->dirty_work);
+    drm_fb_helper_release_fbi(fbdev);
+    drm_framebuffer_unreference(fbdev->fb);

I get a warning that there are still fb's left during unbind:

[   48.666003] WARNING: CPU: 0 PID: 716 at drivers/gpu/drm/drm_crtc.c:3855

drm_mode_config_cleanup+0x180/0x1f4 [drm]

This worked:

Review

Quoted 3 lines
(quoted diff) +2 -1
-       drm_framebuffer_unreference(fbdev->fb);
+       drm_framebuffer_unregister_private(fbdev->fb);
+       drm_framebuffer_cleanup(fbdev->fb);

Well not quite, this doesn't free the bo, so maybe this:

(quoted diff) +2 -1
-       drm_framebuffer_unreference(fbdev->fb);
+       drm_framebuffer_unregister_private(fbdev->fb);
+       sdrm_fb_destroy(fbdev->fb);
Quoted 3 lines

IIRC the reason ref count doesn't drop to zero, had something to do with multiple
fb_set_par calls taking reference but not being dropped later.

So I don't like this at all. If we leak references, we should fix the ref-leak or properly document why this is fine to do. Daniel, what is the exact reason we have unregister_private()? Maybe I should try and trace the ref-leak.

Thanks
David
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#23 lore raw
In reply to David Herrmann
Quoted 53 lines · EST David Herrmann

Hey

On request of Noralf, I picked up the patches and prepared v5. Works fine with Xorg, if configured according to:

    https://lists.freedesktop.org/archives/dri-devel/2014-January/052777.html

If anyone knows how to make Xorg pick it up dynamically without such a static configuration, please let me know.

Thanks
David

David Herrmann (7):
x86/sysfb: add support for 64bit EFI lfb_base x86/sysfb: fix lfb_size calculation of/platform: expose of_platform_device_destroy()
video: add generic framebuffer eviction
drm: switch to sysfb_evict_conflicts()
drm: add SimpleDRM driver
drm/simpledrm: add fbdev fallback support

 MAINTAINERS                                  |   6 +
 arch/x86/kernel/sysfb_simplefb.c             |  39 ++-
 drivers/gpu/drm/Kconfig                      |   3 +
 drivers/gpu/drm/Makefile                     |   1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c      |  24 +-
 drivers/gpu/drm/bochs/bochs_drv.c            |  19 +-
 drivers/gpu/drm/i915/i915_drv.c              |  73 +---
 drivers/gpu/drm/mgag200/mgag200_drv.c        |  27 +-
 drivers/gpu/drm/mgag200/mgag200_main.c       |   9 -
 drivers/gpu/drm/nouveau/nouveau_drm.c        |  33 +-
 drivers/gpu/drm/radeon/radeon_drv.c          |  24 +-
 drivers/gpu/drm/simpledrm/Kconfig            |  19 ++
 drivers/gpu/drm/simpledrm/Makefile           |   9 +
 drivers/gpu/drm/simpledrm/simpledrm.h        |  91 +++++
 drivers/gpu/drm/simpledrm/simpledrm_damage.c | 194 +++++++++++
 drivers/gpu/drm/simpledrm/simpledrm_drv.c    | 477 +++++++++++++++++++++++++++
 drivers/gpu/drm/simpledrm/simpledrm_fbdev.c  | 143 ++++++++
 drivers/gpu/drm/simpledrm/simpledrm_gem.c    | 109 ++++++
 drivers/gpu/drm/simpledrm/simpledrm_kms.c    | 270 +++++++++++++++
 drivers/gpu/drm/simpledrm/simpledrm_of.c     | 265 +++++++++++++++
 drivers/gpu/drm/sun4i/sun4i_drv.c            |  24 +-
 drivers/gpu/drm/vc4/vc4_drv.c                |  25 +-
 drivers/gpu/drm/virtio/virtgpu_drm_bus.c     |  24 +-
 drivers/of/platform.c                        |  35 +-
 drivers/video/Kconfig                        |   4 +
 drivers/video/Makefile                       |   1 +
 drivers/video/sysfb.c                        | 327 ++++++++++++++++++
 include/linux/of_platform.h                  |   1 +
 include/linux/sysfb.h                        |  34 ++
 29 files changed, 2054 insertions(+), 256 deletions(-)
 create mode 100644 drivers/gpu/drm/simpledrm/Kconfig
 create mode 100644 drivers/gpu/drm/simpledrm/Makefile
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm.h
Quoted 10 lines
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_damage.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_drv.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_fbdev.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_gem.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_kms.c
 create mode 100644 drivers/gpu/drm/simpledrm/simpledrm_of.c
 create mode 100644 drivers/video/sysfb.c
 create mode 100644 include/linux/sysfb.h

Hi

I am kind of curious as I do have interest in seeing this merged as well.

There is an email in this thread from 2018, but when I tried to import an mbox file from the whole month for August 2018, for some reason, kmail doesn't see the sender and mailing list recipient in that one, so I will reply to this one, because I was able to import this into my mail client.
https://www.spinics.net/lists/dri-devel/msg185519.html

I was able to get this to build against Linux 4.8, but not against a newer version, some headers seem to have been split, and some things are off by 8 and other things. I could NOT find a git repo, but I was able to find the newest patches I could find, and import those with git am against 4.8 with some tweaks. If that is needed, I can link it, but only if you want.

However in QEMU I wasn't able to figure out how to make it create a /dev/dri/card0 device, even after blacklisting the other modules for qxl, cirrus, etc, and then modprobe-ing simpledrm

In my view something like this is would be useful. There still could be hardware devices that don't have modesetting support (like vmvga in qemu/virt-manager as an example). And most wayland servers need a /dev/dri/card0 device as well as a potential user-mode TTY replacement would also need /dev/dri/card0

I will admit I unfortunately failed to get it to build against master. I couldn't figure out some of the changes, where some new structs were off by a factor of 8.

Thanks

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#24 lore raw

Hi

Am 10.03.21 um 03:50 schrieb nerdopolis:

Quoted 11 lines · EST David Herrmann
Quoted 10 lines

Hey

On request of Noralf, I picked up the patches and prepared v5. Works fine with Xorg, if configured according to:

     https://lists.freedesktop.org/archives/dri-devel/2014-January/052777.html

If anyone knows how to make Xorg pick it up dynamically without such a static configuration, please let me know.

Quoted 3 lines

Hi

I am kind of curious as I do have interest in seeing this merged as well.

Please take a look at [1]. It's not the same driver, but something to the same effect. I know it's been almost a year, but I do work on this and intend to come back with a new version during 2021.

I currently work on fastboot support for the new driver. But it's a complicated matter and takes time. If there's interest, we could talk about merging what's already there.

Best regards
Thomas

[1] https://lore.kernel.org/dri-devel/[email protected]/

Quoted 37 lines

There is an email in this thread from 2018, but when I tried to import an mbox file from the whole month for August 2018, for some reason, kmail doesn't see the sender and mailing list recipient in that one, so I will reply to this one, because I was able to import this into my mail client.
https://www.spinics.net/lists/dri-devel/msg185519.html

I was able to get this to build against Linux 4.8, but not against a newer version, some headers seem to have been split, and some things are off by 8 and other things. I could NOT find a git repo, but I was able to find the newest patches I could find, and import those with git am against 4.8 with some tweaks. If that is needed, I can link it, but only if you want.

However in QEMU I wasn't able to figure out how to make it create a /dev/dri/card0 device, even after blacklisting the other modules for qxl, cirrus, etc, and then modprobe-ing simpledrm

In my view something like this is would be useful. There still could be hardware devices that don't have modesetting support (like vmvga in qemu/virt-manager as an example). And most wayland servers need a /dev/dri/card0 device as well as a potential user-mode TTY replacement would also need /dev/dri/card0

I will admit I unfortunately failed to get it to build against master. I couldn't figure out some of the changes, where some new structs were off by a factor of 8.

Thanks

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Signature · 6 lines
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Felix Imendörffer

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#25 lore raw
Quoted 14 lines · EST Thomas Zimmermann

Hi

Am 10.03.21 um 03:50 schrieb nerdopolis:

Quoted 11 lines · EST David Herrmann
Quoted 10 lines

Hey

On request of Noralf, I picked up the patches and prepared v5. Works fine with Xorg, if configured according to:

     https://lists.freedesktop.org/archives/dri-devel/2014-January/052777.html

If anyone knows how to make Xorg pick it up dynamically without such a static configuration, please let me know.

Quoted 8 lines
Quoted 3 lines

Hi

I am kind of curious as I do have interest in seeing this merged as well.

Please take a look at [1]. It's not the same driver, but something to the same effect. I know it's been almost a year, but I do work on this and intend to come back with a new version during 2021.

Thanks, I'll try that out

Quoted 4 lines

I currently work on fastboot support for the new driver. But it's a complicated matter and takes time. If there's interest, we could talk about merging what's already there.

Quoted 45 lines

Best regards
Thomas

[1]
https://lore.kernel.org/dri-devel/[email protected]/

Quoted 37 lines

There is an email in this thread from 2018, but when I tried to import an mbox file from the whole month for August 2018, for some reason, kmail doesn't see the sender and mailing list recipient in that one, so I will reply to this one, because I was able to import this into my mail client.
https://www.spinics.net/lists/dri-devel/msg185519.html

I was able to get this to build against Linux 4.8, but not against a newer version, some headers seem to have been split, and some things are off by 8 and other things. I could NOT find a git repo, but I was able to find the newest patches I could find, and import those with git am against 4.8 with some tweaks. If that is needed, I can link it, but only if you want.

However in QEMU I wasn't able to figure out how to make it create a /dev/dri/card0 device, even after blacklisting the other modules for qxl, cirrus, etc, and then modprobe-ing simpledrm

In my view something like this is would be useful. There still could be hardware devices that don't have modesetting support (like vmvga in qemu/virt-manager as an example). And most wayland servers need a /dev/dri/card0 device as well as a potential user-mode TTY replacement would also need /dev/dri/card0

I will admit I unfortunately failed to get it to build against master. I couldn't figure out some of the changes, where some new structs were off by a factor of 8.

Thanks

_______________________________________________
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

#26 lore raw
In reply to Thomas Zimmermann
Quoted 26 lines · EST Thomas Zimmermann

Hi

Am 10.03.21 um 03:50 schrieb nerdopolis:

Quoted 11 lines · EST David Herrmann
Quoted 10 lines

Hey

On request of Noralf, I picked up the patches and prepared v5. Works fine with Xorg, if configured according to:

     https://lists.freedesktop.org/archives/dri-devel/2014-January/052777.html

If anyone knows how to make Xorg pick it up dynamically without such a static configuration, please let me know.

Quoted 3 lines

Hi

I am kind of curious as I do have interest in seeing this merged as well.

Please take a look at [1]. It's not the same driver, but something to the same effect. I know it's been almost a year, but I do work on this and intend to come back with a new version during 2021.

I currently work on fastboot support for the new driver. But it's a complicated matter and takes time. If there's interest, we could talk about merging what's already there.

Quoted 45 lines

Best regards
Thomas

[1]
https://lore.kernel.org/dri-devel/[email protected]/

Quoted 37 lines

There is an email in this thread from 2018, but when I tried to import an mbox file from the whole month for August 2018, for some reason, kmail doesn't see the sender and mailing list recipient in that one, so I will reply to this one, because I was able to import this into my mail client.
https://www.spinics.net/lists/dri-devel/msg185519.html

I was able to get this to build against Linux 4.8, but not against a newer version, some headers seem to have been split, and some things are off by 8 and other things. I could NOT find a git repo, but I was able to find the newest patches I could find, and import those with git am against 4.8 with some tweaks. If that is needed, I can link it, but only if you want.

However in QEMU I wasn't able to figure out how to make it create a /dev/dri/card0 device, even after blacklisting the other modules for qxl, cirrus, etc, and then modprobe-ing simpledrm

In my view something like this is would be useful. There still could be hardware devices that don't have modesetting support (like vmvga in qemu/virt-manager as an example). And most wayland servers need a /dev/dri/card0 device as well as a potential user-mode TTY replacement would also need /dev/dri/card0

I will admit I unfortunately failed to get it to build against master. I couldn't figure out some of the changes, where some new structs were off by a factor of 8.

Thanks

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Hi

I tried simplekms against v5.9, and it built, and it runs, and is pretty neat.

I tried using the qxl, cirrus, and vmware card in QEMU. Weston starts on all of them. And I did ensure that the simplekms driver was being used

That is, it works after adding GRUB_GFXPAYLOAD_LINUX=keep , to avoid having to set a VGA option. (although not sure the equivalent in syslinux yet)

Thanks.

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

maintainer Tested-by nerdopolis
#27 lore raw

Hi

Am 12.03.21 um 04:49 schrieb nerdopolis:

Quoted 72 lines · EST Thomas Zimmermann
Quoted 26 lines

Hi

Am 10.03.21 um 03:50 schrieb nerdopolis:

Quoted 11 lines · EST David Herrmann
Quoted 10 lines

Hey

On request of Noralf, I picked up the patches and prepared v5. Works fine with Xorg, if configured according to:

      https://lists.freedesktop.org/archives/dri-devel/2014-January/052777.html

If anyone knows how to make Xorg pick it up dynamically without such a static configuration, please let me know.

Quoted 3 lines

Hi

I am kind of curious as I do have interest in seeing this merged as well.

Please take a look at [1]. It's not the same driver, but something to the same effect. I know it's been almost a year, but I do work on this and intend to come back with a new version during 2021.

I currently work on fastboot support for the new driver. But it's a complicated matter and takes time. If there's interest, we could talk about merging what's already there.

Quoted 45 lines

Best regards
Thomas

[1]
https://lore.kernel.org/dri-devel/[email protected]/

Quoted 37 lines

There is an email in this thread from 2018, but when I tried to import an mbox file from the whole month for August 2018, for some reason, kmail doesn't see the sender and mailing list recipient in that one, so I will reply to this one, because I was able to import this into my mail client.
https://www.spinics.net/lists/dri-devel/msg185519.html

I was able to get this to build against Linux 4.8, but not against a newer version, some headers seem to have been split, and some things are off by 8 and other things. I could NOT find a git repo, but I was able to find the newest patches I could find, and import those with git am against 4.8 with some tweaks. If that is needed, I can link it, but only if you want.

However in QEMU I wasn't able to figure out how to make it create a /dev/dri/card0 device, even after blacklisting the other modules for qxl, cirrus, etc, and then modprobe-ing simpledrm

In my view something like this is would be useful. There still could be hardware devices that don't have modesetting support (like vmvga in qemu/virt-manager as an example). And most wayland servers need a /dev/dri/card0 device as well as a potential user-mode TTY replacement would also need /dev/dri/card0

I will admit I unfortunately failed to get it to build against master. I couldn't figure out some of the changes, where some new structs were off by a factor of 8.

Thanks

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Quoted 6 lines

Hi

I tried simplekms against v5.9, and it built, and it runs, and is pretty neat.

I tried using the qxl, cirrus, and vmware card in QEMU. Weston starts on all of them. And I did ensure that the simplekms driver was being used

Cool! Thanks a lot. When I submit the next patchset can I add

to the tags?

Quoted 3 lines

That is, it works after adding GRUB_GFXPAYLOAD_LINUX=keep , to avoid having to set a VGA option. (although not sure the equivalent in syslinux yet)

Yeah, it's a known 'limitation.' (1) But it's usually something that Linux distributions take care of.

The rsp kernel feature needs a set up from the firmware/bootloader/etc. Once the driver has been merged, added other generic drivers (EFI, VESA, etc) should be a lot easier. Those would maybe not require the firmware setup.

Best regards
Thomas

(1) Well, it's the way it's supposed to work.

Quoted 5 lines

Thanks.

Signature · 6 lines
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Felix Imendörffer

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

#28 lore raw
Quoted 79 lines · EST Thomas Zimmermann

Hi

Am 12.03.21 um 04:49 schrieb nerdopolis:

Quoted 76 lines · EST Thomas Zimmermann
Quoted 26 lines

Hi

Am 10.03.21 um 03:50 schrieb nerdopolis:

Quoted 11 lines · EST David Herrmann
Quoted 10 lines

Hey

On request of Noralf, I picked up the patches and prepared v5. Works fine with Xorg, if configured according to:

      https://lists.freedesktop.org/archives/dri-devel/2014-January/052777.html

If anyone knows how to make Xorg pick it up dynamically without such a static configuration, please let me know.

Quoted 3 lines

Hi

I am kind of curious as I do have interest in seeing this merged as well.

Please take a look at [1]. It's not the same driver, but something to the same effect. I know it's been almost a year, but I do work on this and intend to come back with a new version during 2021.

I currently work on fastboot support for the new driver. But it's a complicated matter and takes time. If there's interest, we could talk about merging what's already there.

Quoted 45 lines

Best regards
Thomas

[1]
https://lore.kernel.org/dri-devel/[email protected]/

Quoted 37 lines

There is an email in this thread from 2018, but when I tried to import an mbox file from the whole month for August 2018, for some reason, kmail doesn't see the sender and mailing list recipient in that one, so I will reply to this one, because I was able to import this into my mail client.
https://www.spinics.net/lists/dri-devel/msg185519.html

I was able to get this to build against Linux 4.8, but not against a newer version, some headers seem to have been split, and some things are off by 8 and other things. I could NOT find a git repo, but I was able to find the newest patches I could find, and import those with git am against 4.8 with some tweaks. If that is needed, I can link it, but only if you want.

However in QEMU I wasn't able to figure out how to make it create a /dev/dri/card0 device, even after blacklisting the other modules for qxl, cirrus, etc, and then modprobe-ing simpledrm

In my view something like this is would be useful. There still could be hardware devices that don't have modesetting support (like vmvga in qemu/virt-manager as an example). And most wayland servers need a /dev/dri/card0 device as well as a potential user-mode TTY replacement would also need /dev/dri/card0

I will admit I unfortunately failed to get it to build against master. I couldn't figure out some of the changes, where some new structs were off by a factor of 8.

Thanks

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Hi

I tried simplekms against v5.9, and it built, and it runs, and is pretty neat.

Quoted 9 lines
Quoted 2 lines

I tried using the qxl, cirrus, and vmware card in QEMU. Weston starts on all of them. And I did ensure that the simplekms driver was being used

Cool! Thanks a lot. When I submit the next patchset can I add

to the tags?

Sure!

Quoted 12 lines
Quoted 3 lines

That is, it works after adding GRUB_GFXPAYLOAD_LINUX=keep , to avoid having to set a VGA option. (although not sure the equivalent in syslinux yet)

Yeah, it's a known 'limitation.' (1) But it's usually something that Linux distributions take care of.

The rsp kernel feature needs a set up from the firmware/bootloader/etc. Once the driver has been merged, added other generic drivers (EFI, VESA, etc) should be a lot easier. Those would maybe not require the firmware setup.

Quoted 12 lines

Best regards
Thomas

(1) Well, it's the way it's supposed to work.

Quoted 5 lines

Thanks.

_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel