Message ID | CANq1E4ScQsU6Jo5PxrCtrecFmA7nY=1xP48TYh8Cbwp=j=E3vw@mail.gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Den 05.09.2016 13:19, skrev David Herrmann: > Hi > > On Sat, Sep 3, 2016 at 2:06 PM, Noralf Trønnes <noralf@tronnes.org> wrote: >> Den 02.09.2016 10:22, skrev 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. >>> >>> Signed-off-by: David Herrmann <dh.herrmann@gmail.com> >>> --- >>> 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 >>> >>> diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig >>> index 3c20af9..56a8294 100644 >>> --- a/drivers/video/Kconfig >>> +++ b/drivers/video/Kconfig >>> @@ -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 >>> diff --git a/drivers/video/Makefile b/drivers/video/Makefile >>> index 9ad3c17..df7bd75 100644 >>> --- a/drivers/video/Makefile >>> +++ b/drivers/video/Makefile >>> @@ -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/ >>> diff --git a/drivers/video/sysfb.c b/drivers/video/sysfb.c >>> new file mode 100644 >>> index 0000000..00585c9 >>> --- /dev/null >>> +++ b/drivers/video/sysfb.c >>> @@ -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")) { >> >> 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")) { > Thanks for the hint, but this would skip devices that are not bound. > How about the attached hunk? > > Thanks > David > > diff --git a/drivers/video/sysfb.c b/drivers/video/sysfb.c > index 0f039c6..a4ace3f 100644 > --- a/drivers/video/sysfb.c > +++ b/drivers/video/sysfb.c > @@ -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; > This worked fine. Noralf.
diff --git a/drivers/video/sysfb.c b/drivers/video/sysfb.c index 0f039c6..a4ace3f 100644 --- a/drivers/video/sysfb.c +++ b/drivers/video/sysfb.c @@ -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;