summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/gpu/drm-internals.rst12
-rw-r--r--drivers/gpu/drm/Makefile2
-rw-r--r--drivers/gpu/drm/drm_aperture.c114
-rw-r--r--include/drm/drm_aperture.h31
4 files changed, 158 insertions, 1 deletions
diff --git a/Documentation/gpu/drm-internals.rst b/Documentation/gpu/drm-internals.rst
index 12272b168580..06af044c882f 100644
--- a/Documentation/gpu/drm-internals.rst
+++ b/Documentation/gpu/drm-internals.rst
@@ -75,6 +75,18 @@ update it, its value is mostly useless. The DRM core prints it to the
kernel log at initialization time and passes it to userspace through the
DRM_IOCTL_VERSION ioctl.
+Managing Ownership of the Framebuffer Aperture
+----------------------------------------------
+
+.. kernel-doc:: drivers/gpu/drm/drm_aperture.c
+ :doc: overview
+
+.. kernel-doc:: include/drm/drm_aperture.h
+ :internal:
+
+.. kernel-doc:: drivers/gpu/drm/drm_aperture.c
+ :export:
+
Device Instance and Driver Handling
-----------------------------------
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 5279db4392df..89e747fedc00 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -3,7 +3,7 @@
# Makefile for the drm device driver. This driver provides support for the
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
-drm-y := drm_auth.o drm_cache.o \
+drm-y := drm_aperture.o drm_auth.o drm_cache.o \
drm_file.o drm_gem.o drm_ioctl.o drm_irq.o \
drm_drv.o \
drm_sysfs.o drm_hashtab.o drm_mm.o \
diff --git a/drivers/gpu/drm/drm_aperture.c b/drivers/gpu/drm/drm_aperture.c
new file mode 100644
index 000000000000..929dcbc0758a
--- /dev/null
+++ b/drivers/gpu/drm/drm_aperture.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: MIT
+
+#include <drm/drm_aperture.h>
+#include <drm/drm_fb_helper.h>
+
+/**
+ * DOC: overview
+ *
+ * A graphics device might be supported by different drivers, but only one
+ * driver can be active at any given time. Many systems load a generic
+ * graphics drivers, such as EFI-GOP or VESA, early during the boot process.
+ * During later boot stages, they replace the generic driver with a dedicated,
+ * hardware-specific driver. To take over the device the dedicated driver
+ * first has to remove the generic driver. DRM aperture functions manage
+ * ownership of DRM framebuffer memory and hand-over between drivers.
+ *
+ * DRM drivers should call drm_aperture_remove_conflicting_framebuffers()
+ * at the top of their probe function. The function removes any generic
+ * driver that is currently associated with the given framebuffer memory.
+ * If the framebuffer is located at PCI BAR 0, the rsp code looks as in the
+ * example given below.
+ *
+ * .. code-block:: c
+ *
+ * static int remove_conflicting_framebuffers(struct pci_dev *pdev)
+ * {
+ * bool primary = false;
+ * resource_size_t base, size;
+ * int ret;
+ *
+ * base = pci_resource_start(pdev, 0);
+ * size = pci_resource_len(pdev, 0);
+ * #ifdef CONFIG_X86
+ * primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
+ * #endif
+ *
+ * return drm_aperture_remove_conflicting_framebuffers(base, size, primary,
+ * "example driver");
+ * }
+ *
+ * static int probe(struct pci_dev *pdev)
+ * {
+ * int ret;
+ *
+ * // Remove any generic drivers...
+ * ret = remove_conflicting_framebuffers(pdev);
+ * if (ret)
+ * return ret;
+ *
+ * // ... and initialize the hardware.
+ * ...
+ *
+ * drm_dev_register();
+ *
+ * return 0;
+ * }
+ *
+ * PCI device drivers should call
+ * drm_aperture_remove_conflicting_pci_framebuffers() and let it detect the
+ * framebuffer apertures automatically. Device drivers without knowledge of
+ * the framebuffer's location shall call drm_aperture_remove_framebuffers(),
+ * which removes all drivers for known framebuffer.
+ */
+
+/**
+ * drm_aperture_remove_conflicting_framebuffers - remove existing framebuffers in the given range
+ * @base: the aperture's base address in physical memory
+ * @size: aperture size in bytes
+ * @primary: also kick vga16fb if present
+ * @name: requesting driver name
+ *
+ * This function removes graphics device drivers which use memory range described by
+ * @base and @size.
+ *
+ * Returns:
+ * 0 on success, or a negative errno code otherwise
+ */
+int drm_aperture_remove_conflicting_framebuffers(resource_size_t base, resource_size_t size,
+ bool primary, const char *name)
+{
+ struct apertures_struct *a;
+ int ret;
+
+ a = alloc_apertures(1);
+ if (!a)
+ return -ENOMEM;
+
+ a->ranges[0].base = base;
+ a->ranges[0].size = size;
+
+ ret = drm_fb_helper_remove_conflicting_framebuffers(a, name, primary);
+ kfree(a);
+
+ return ret;
+}
+EXPORT_SYMBOL(drm_aperture_remove_conflicting_framebuffers);
+
+/**
+ * drm_aperture_remove_conflicting_pci_framebuffers - remove existing framebuffers for PCI devices
+ * @pdev: PCI device
+ * @name: requesting driver name
+ *
+ * This function removes graphics device drivers using memory range configured
+ * for any of @pdev's memory bars. The function assumes that PCI device with
+ * shadowed ROM drives a primary display and so kicks out vga16fb.
+ *
+ * Returns:
+ * 0 on success, or a negative errno code otherwise
+ */
+int drm_aperture_remove_conflicting_pci_framebuffers(struct pci_dev *pdev, const char *name)
+{
+ return drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, name);
+}
+EXPORT_SYMBOL(drm_aperture_remove_conflicting_pci_framebuffers);
diff --git a/include/drm/drm_aperture.h b/include/drm/drm_aperture.h
new file mode 100644
index 000000000000..23cc01647ed3
--- /dev/null
+++ b/include/drm/drm_aperture.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: MIT */
+
+#ifndef _DRM_APERTURE_H_
+#define _DRM_APERTURE_H_
+
+#include <linux/types.h>
+
+struct pci_dev;
+
+int drm_aperture_remove_conflicting_framebuffers(resource_size_t base, resource_size_t size,
+ bool primary, const char *name);
+
+int drm_aperture_remove_conflicting_pci_framebuffers(struct pci_dev *pdev, const char *name);
+
+/**
+ * drm_aperture_remove_framebuffers - remove all existing framebuffers
+ * @primary: also kick vga16fb if present
+ * @name: requesting driver name
+ *
+ * This function removes all graphics device drivers. Use this function on systems
+ * that can have their framebuffer located anywhere in memory.
+ *
+ * Returns:
+ * 0 on success, or a negative errno code otherwise
+ */
+static inline int drm_aperture_remove_framebuffers(bool primary, const char *name)
+{
+ return drm_aperture_remove_conflicting_framebuffers(0, (resource_size_t)-1, primary, name);
+}
+
+#endif