fbdev: fbmem: add a helper to determine if an aperture is used by a fw fb
authorAlex Deucher <alexander.deucher@amd.com>
Thu, 23 Dec 2021 03:41:18 +0000 (22:41 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 11 Jan 2022 14:35:16 +0000 (15:35 +0100)
commit 9a45ac2320d0a6ae01880a30d4b86025fce4061b upstream.

Add a function for drivers to check if the a firmware initialized
fb is corresponds to their aperture.  This allows drivers to check if the
device corresponds to what the firmware set up as the display device.

Bug: https://bugzilla.kernel.org/show_bug.cgi?id=215203
Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1840
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/video/fbdev/core/fbmem.c
include/linux/fb.h

index 7420d2c16e47e34f8acf94fd70f7417133e62773..7bd5e2a4a9da5633b16fe0874211b1479803a217 100644 (file)
@@ -1759,6 +1759,53 @@ int remove_conflicting_framebuffers(struct apertures_struct *a,
 }
 EXPORT_SYMBOL(remove_conflicting_framebuffers);
 
+/**
+ * is_firmware_framebuffer - detect if firmware-configured framebuffer matches
+ * @a: memory range, users of which are to be checked
+ *
+ * This function checks framebuffer devices (initialized by firmware/bootloader)
+ * which use memory range described by @a. If @a matchesm the function returns
+ * true, otherwise false.
+ */
+bool is_firmware_framebuffer(struct apertures_struct *a)
+{
+       bool do_free = false;
+       bool found = false;
+       int i;
+
+       if (!a) {
+               a = alloc_apertures(1);
+               if (!a)
+                       return false;
+
+               a->ranges[0].base = 0;
+               a->ranges[0].size = ~0;
+               do_free = true;
+       }
+
+       mutex_lock(&registration_lock);
+       /* check all firmware fbs and kick off if the base addr overlaps */
+       for_each_registered_fb(i) {
+               struct apertures_struct *gen_aper;
+
+               if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE))
+                       continue;
+
+               gen_aper = registered_fb[i]->apertures;
+               if (fb_do_apertures_overlap(gen_aper, a)) {
+                       found = true;
+                       break;
+               }
+       }
+       mutex_unlock(&registration_lock);
+
+       if (do_free)
+               kfree(a);
+
+       return found;
+}
+EXPORT_SYMBOL(is_firmware_framebuffer);
+
 /**
  * remove_conflicting_pci_framebuffers - remove firmware-configured framebuffers for PCI devices
  * @pdev: PCI device
index 5950f8f5dc74d657268eafe23ddc1bc146ef0b05..02f362c661c8003928a928bd1a92bc6db2b0bd2b 100644 (file)
@@ -610,6 +610,7 @@ extern int remove_conflicting_pci_framebuffers(struct pci_dev *pdev,
                                               const char *name);
 extern int remove_conflicting_framebuffers(struct apertures_struct *a,
                                           const char *name, bool primary);
+extern bool is_firmware_framebuffer(struct apertures_struct *a);
 extern int fb_prepare_logo(struct fb_info *fb_info, int rotate);
 extern int fb_show_logo(struct fb_info *fb_info, int rotate);
 extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size);