fbdev: add remove_conflicting_pci_framebuffers()
authorMichał Mirosław <mirq-linux@rere.qmqm.pl>
Sat, 1 Sep 2018 14:08:45 +0000 (16:08 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 3 Sep 2018 16:15:40 +0000 (18:15 +0200)
Almost all PCI drivers using remove_conflicting_framebuffers() wrap it
with the same code.

v2: add kerneldoc for DRM helper
v3: propagate remove_conflicting_framebuffers() return value
  + move kerneldoc to where function is implemented

Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Acked-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/7db1c278276de420eb45a1b71d06b5eb6bbd49ef.1535810304.git.mirq-linux@rere.qmqm.pl
drivers/video/fbdev/core/fbmem.c
include/drm/drm_fb_helper.h
include/linux/fb.h

index 6e9961b714428eb978aa5217542467e86723fba5..5ffadc8e681d2ac4560113b5c42f5caf28ab19c4 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/fb.h>
 #include <linux/fbcon.h>
 #include <linux/mem_encrypt.h>
+#include <linux/pci.h>
 
 #include <asm/fb.h>
 
@@ -1830,6 +1831,40 @@ int remove_conflicting_framebuffers(struct apertures_struct *a,
 }
 EXPORT_SYMBOL(remove_conflicting_framebuffers);
 
+/**
+ * remove_conflicting_pci_framebuffers - remove firmware-configured framebuffers for PCI devices
+ * @pdev: PCI device
+ * @resource_id: index of PCI BAR configuring framebuffer memory
+ * @name: requesting driver name
+ *
+ * This function removes framebuffer devices (eg. initialized by firmware)
+ * using memory range configured for @pdev's BAR @resource_id.
+ *
+ * The function assumes that PCI device with shadowed ROM drives a primary
+ * display and so kicks out vga16fb.
+ */
+int remove_conflicting_pci_framebuffers(struct pci_dev *pdev, int res_id, const char *name)
+{
+       struct apertures_struct *ap;
+       bool primary = false;
+       int err;
+
+       ap = alloc_apertures(1);
+       if (!ap)
+               return -ENOMEM;
+
+       ap->ranges[0].base = pci_resource_start(pdev, res_id);
+       ap->ranges[0].size = pci_resource_len(pdev, res_id);
+#ifdef CONFIG_X86
+       primary = pdev->resource[PCI_ROM_RESOURCE].flags &
+                                       IORESOURCE_ROM_SHADOW;
+#endif
+       err = remove_conflicting_framebuffers(ap, name, primary);
+       kfree(ap);
+       return err;
+}
+EXPORT_SYMBOL(remove_conflicting_pci_framebuffers);
+
 /**
  *     register_framebuffer - registers a frame buffer device
  *     @fb_info: frame buffer info structure
index 5db08c8f1d258a6e4ef6336831f15001e8780519..8b6ab3200a2c66210a7ebf889999288c9c773d3f 100644 (file)
@@ -615,4 +615,16 @@ drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a,
 #endif
 }
 
+static inline int
+drm_fb_helper_remove_conflicting_pci_framebuffers(struct pci_dev *pdev,
+                                                 int resource_id,
+                                                 const char *name)
+{
+#if IS_REACHABLE(CONFIG_FB)
+       return remove_conflicting_pci_framebuffers(pdev, resource_id, name);
+#else
+       return 0;
+#endif
+}
+
 #endif
index 3e7e75383d327d2dbd2e81410033cd26c193e003..3cd375dafd0eff9d5b56cfc3cc603a6c945eacc3 100644 (file)
@@ -632,6 +632,8 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
 extern int register_framebuffer(struct fb_info *fb_info);
 extern int unregister_framebuffer(struct fb_info *fb_info);
 extern int unlink_framebuffer(struct fb_info *fb_info);
+extern int remove_conflicting_pci_framebuffers(struct pci_dev *pdev, int res_id,
+                                              const char *name);
 extern int remove_conflicting_framebuffers(struct apertures_struct *a,
                                           const char *name, bool primary);
 extern int fb_prepare_logo(struct fb_info *fb_info, int rotate);