diff options
| author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2015-11-23 09:04:05 +0100 |
|---|---|---|
| committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2015-11-23 09:04:05 +0100 |
| commit | 92907cbbef8625bb3998d1eb385fc88f23c97a3f (patch) | |
| tree | 15626ff9287e37c3cb81c7286d6db5a7fd77c854 /Documentation/DocBook/gpu.tmpl | |
| parent | 15fbfccfe92c62ae8d1ecc647c44157ed01ac02e (diff) | |
| parent | 1ec218373b8ebda821aec00bb156a9c94fad9cd4 (diff) | |
Merge tag 'v4.4-rc2' into drm-intel-next-queued
Linux 4.4-rc2
Backmerge to get at
commit 1b0e3a049efe471c399674fd954500ce97438d30
Author: Imre Deak <imre.deak@intel.com>
Date: Thu Nov 5 23:04:11 2015 +0200
drm/i915/skl: disable display side power well support for now
so that we can proplery re-eanble skl power wells in -next.
Conflicts are just adjacent lines changed, except for intel_fbdev.c
where we need to interleave the changs. Nothing nefarious.
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Diffstat (limited to 'Documentation/DocBook/gpu.tmpl')
| -rw-r--r-- | Documentation/DocBook/gpu.tmpl | 4290 |
1 files changed, 4290 insertions, 0 deletions
diff --git a/Documentation/DocBook/gpu.tmpl b/Documentation/DocBook/gpu.tmpl new file mode 100644 index 000000000000..3bf810ec75b1 --- /dev/null +++ b/Documentation/DocBook/gpu.tmpl @@ -0,0 +1,4290 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" + "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []> + +<book id="gpuDevelopersGuide"> + <bookinfo> + <title>Linux GPU Driver Developer's Guide</title> + + <authorgroup> + <author> + <firstname>Jesse</firstname> + <surname>Barnes</surname> + <contrib>Initial version</contrib> + <affiliation> + <orgname>Intel Corporation</orgname> + <address> + <email>jesse.barnes@intel.com</email> + </address> + </affiliation> + </author> + <author> + <firstname>Laurent</firstname> + <surname>Pinchart</surname> + <contrib>Driver internals</contrib> + <affiliation> + <orgname>Ideas on board SPRL</orgname> + <address> + <email>laurent.pinchart@ideasonboard.com</email> + </address> + </affiliation> + </author> + <author> + <firstname>Daniel</firstname> + <surname>Vetter</surname> + <contrib>Contributions all over the place</contrib> + <affiliation> + <orgname>Intel Corporation</orgname> + <address> + <email>daniel.vetter@ffwll.ch</email> + </address> + </affiliation> + </author> + <author> + <firstname>Lukas</firstname> + <surname>Wunner</surname> + <contrib>vga_switcheroo documentation</contrib> + <affiliation> + <address> + <email>lukas@wunner.de</email> + </address> + </affiliation> + </author> + </authorgroup> + + <copyright> + <year>2008-2009</year> + <year>2013-2014</year> + <holder>Intel Corporation</holder> + </copyright> + <copyright> + <year>2012</year> + <holder>Laurent Pinchart</holder> + </copyright> + <copyright> + <year>2015</year> + <holder>Lukas Wunner</holder> + </copyright> + + <legalnotice> + <para> + The contents of this file may be used under the terms of the GNU + General Public License version 2 (the "GPL") as distributed in + the kernel source COPYING file. + </para> + </legalnotice> + + <revhistory> + <!-- Put document revisions here, newest first. --> + <revision> + <revnumber>1.0</revnumber> + <date>2012-07-13</date> + <authorinitials>LP</authorinitials> + <revremark>Added extensive documentation about driver internals. + </revremark> + </revision> + <revision> + <revnumber>1.1</revnumber> + <date>2015-10-11</date> + <authorinitials>LW</authorinitials> + <revremark>Added vga_switcheroo documentation. + </revremark> + </revision> + </revhistory> + </bookinfo> + +<toc></toc> + +<part id="drmCore"> + <title>DRM Core</title> + <partintro> + <para> + This first part of the GPU Driver Developer's Guide documents core DRM + code, helper libraries for writing drivers and generic userspace + interfaces exposed by DRM drivers. + </para> + </partintro> + + <chapter id="drmIntroduction"> + <title>Introduction</title> + <para> + The Linux DRM layer contains code intended to support the needs + of complex graphics devices, usually containing programmable + pipelines well suited to 3D graphics acceleration. Graphics + drivers in the kernel may make use of DRM functions to make + tasks like memory management, interrupt handling and DMA easier, + and provide a uniform interface to applications. + </para> + <para> + A note on versions: this guide covers features found in the DRM + tree, including the TTM memory manager, output configuration and + mode setting, and the new vblank internals, in addition to all + the regular features found in current kernels. + </para> + <para> + [Insert diagram of typical DRM stack here] + </para> + </chapter> + + <!-- Internals --> + + <chapter id="drmInternals"> + <title>DRM Internals</title> + <para> + This chapter documents DRM internals relevant to driver authors + and developers working to add support for the latest features to + existing drivers. + </para> + <para> + First, we go over some typical driver initialization + requirements, like setting up command buffers, creating an + initial output configuration, and initializing core services. + Subsequent sections cover core internals in more detail, + providing implementation notes and examples. + </para> + <para> + The DRM layer provides several services to graphics drivers, + many of them driven by the application interfaces it provides + through libdrm, the library that wraps most of the DRM ioctls. + These include vblank event handling, memory + management, output management, framebuffer management, command + submission & fencing, suspend/resume support, and DMA + services. + </para> + + <!-- Internals: driver init --> + + <sect1> + <title>Driver Initialization</title> + <para> + At the core of every DRM driver is a <structname>drm_driver</structname> + structure. Drivers typically statically initialize a drm_driver structure, + and then pass it to <function>drm_dev_alloc()</function> to allocate a + device instance. After the device instance is fully initialized it can be + registered (which makes it accessible from userspace) using + <function>drm_dev_register()</function>. + </para> + <para> + The <structname>drm_driver</structname> structure contains static + information that describes the driver and features it supports, and + pointers to methods that the DRM core will call to implement the DRM API. + We will first go through the <structname>drm_driver</structname> static + information fields, and will then describe individual operations in + details as they get used in later sections. + </para> + <sect2> + <title>Driver Information</title> + <sect3> + <title>Driver Features</title> + <para> + Drivers inform the DRM core about their requirements and supported + features by setting appropriate flags in the + <structfield>driver_features</structfield> field. Since those flags + influence the DRM core behaviour since registration time, most of them + must be set to registering the <structname>drm_driver</structname> + instance. + </para> + <synopsis>u32 driver_features;</synopsis> + <variablelist> + <title>Driver Feature Flags</title> + <varlistentry> + <term>DRIVER_USE_AGP</term> + <listitem><para> + Driver uses AGP interface, the DRM core will manage AGP resources. + </para></listitem> + </varlistentry> + <varlistentry> + <term>DRIVER_REQUIRE_AGP</term> + <listitem><para> + Driver needs AGP interface to function. AGP initialization failure + will become a fatal error. + </para></listitem> + </varlistentry> + <varlistentry> + <term>DRIVER_PCI_DMA</term> + <listitem><para> + Driver is capable of PCI DMA, mapping of PCI DMA buffers to + userspace will be enabled. Deprecated. + </para></listitem> + </varlistentry> + <varlistentry> + <term>DRIVER_SG</term> + <listitem><para> + Driver can perform scatter/gather DMA, allocation and mapping of + scatter/gather buffers will be enabled. Deprecated. + </para></listitem> + </varlistentry> + <varlistentry> + <term>DRIVER_HAVE_DMA</term> + <listitem><para> + Driver supports DMA, the userspace DMA API will be supported. + Deprecated. + </para></listitem> + </varlistentry> + <varlistentry> + <term>DRIVER_HAVE_IRQ</term><term>DRIVER_IRQ_SHARED</term> + <listitem><para> + DRIVER_HAVE_IRQ indicates whether the driver has an IRQ handler + managed by the DRM Core. The core will support simple IRQ handler + installation when the flag is set. The installation process is + described in <xref linkend="drm-irq-registration"/>.</para> + <para>DRIVER_IRQ_SHARED indicates whether the device & handler + support shared IRQs (note that this is required of PCI drivers). + </para></listitem> + </varlistentry> + <varlistentry> + <term>DRIVER_GEM</term> + <listitem><para> + Driver use the GEM memory manager. + </para></listitem> + </varlistentry> + <varlistentry> + <term>DRIVER_MODESET</term> + <listitem><para> + Driver supports mode setting interfaces (KMS). + </para></listitem> + </varlistentry> + <varlistentry> + <term>DRIVER_PRIME</term> + <listitem><para> + Driver implements DRM PRIME buffer sharing. + </para></listitem> + </varlistentry> + <varlistentry> + <term>DRIVER_RENDER</term> + <listitem><para> + Driver supports dedicated render nodes. + </para></listitem> + </varlistentry> + <varlistentry> + <term>DRIVER_ATOMIC</term> + <listitem><para> + Driver supports atomic properties. In this case the driver + must implement appropriate obj->atomic_get_property() vfuncs + for any modeset objects with driver specific properties. + </para></listitem> + </varlistentry> + </variablelist> + </sect3> + <sect3> + <title>Major, Minor and Patchlevel</title> + <synopsis>int major; +int minor; +int patchlevel;</synopsis> + <para> + The DRM core identifies driver versions by a major, minor and patch + level triplet. The information is printed to the kernel log at + initialization time and passed to userspace through the + DRM_IOCTL_VERSION ioctl. + </para> + <para> + The major and minor numbers are also used to verify the requested driver + API version passed to DRM_IOCTL_SET_VERSION. When the driver API changes + between minor versions, applications can call DRM_IOCTL_SET_VERSION to + select a specific version of the API. If the requested major isn't equal + to the driver major, or the requested minor is larger than the driver + minor, the DRM_IOCTL_SET_VERSION call will return an error. Otherwise + the driver's set_version() method will be called with the requested + version. + </para> + </sect3> + <sect3> + <title>Name, Description and Date</title> + <synopsis>char *name; +char *desc; +char *date;</synopsis> + <para> + The driver name is printed to the kernel log at initialization time, + used for IRQ registration and passed to userspace through + DRM_IOCTL_VERSION. + </para> + <para> + The driver description is a purely informative string passed to + userspace through the DRM_IOCTL_VERSION ioctl and otherwise unused by + the kernel. + </para> + <para> + The driver date, formatted as YYYYMMDD, is meant to identify the date of + the latest modification to the driver. However, as most drivers fail to + 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. + </para> + </sect3> + </sect2> + <sect2> + <title>Device Instance and Driver Handling</title> +!Pdrivers/gpu/drm/drm_drv.c driver instance overview +!Edrivers/gpu/drm/drm_drv.c + </sect2> + <sect2> + <title>Driver Load</title> + <sect3 id="drm-irq-registration"> + <title>IRQ Registration</title> + <para> + The DRM core tries to facilitate IRQ handler registration and + unregistration by providing <function>drm_irq_install</function> and + <function>drm_irq_uninstall</function> functions. Those functions only + support a single interrupt per device, devices that use more than one + IRQs need to be handled manually. + </para> + <sect4> + <title>Managed IRQ Registration</title> + <para> + <function>drm_irq_install</function> starts by calling the + <methodname>irq_preinstall</methodname> driver operation. The operation + is optional and must make sure that the interrupt will not get fired by + clearing all pending interrupt flags or disabling the interrupt. + </para> + <para> + The passed-in IRQ will then be requested by a call to + <function>request_irq</function>. If the DRIVER_IRQ_SHARED driver + feature flag is set, a shared (IRQF_SHARED) IRQ handler will be + requested. + </para> + <para> + The IRQ handler function must be provided as the mandatory irq_handler + driver operation. It will get passed directly to + <function>request_irq</function> and thus has the same prototype as all + IRQ handlers. It will get called with a pointer to the DRM device as the + second argument. + </para> + <para> + Finally the function calls the optional + <methodname>irq_postinstall</methodname> driver operation. The operation + usually enables interrupts (excluding the vblank interrupt, which is + enabled separately), but drivers may choose to enable/disable interrupts + at a different time. + </para> + <para> + <function>drm_irq_uninstall</function> is similarly used to uninstall an + IRQ handler. It starts by waking up all processes waiting on a vblank + interrupt to make sure they don't hang, and then calls the optional + <methodname>irq_uninstall</methodname> driver operation. The operation + must disable all hardware interrupts. Finally the function frees the IRQ + by calling <function>free_irq</function>. + </para> + </sect4> + <sect4> + <title>Manual IRQ Registration</title> + <para> + Drivers that require multiple interrupt handlers can't use the managed + IRQ registration functions. In that case IRQs must be registered and + unregistered manually (usually with the <function>request_irq</function> + and <function>free_irq</function> functions, or their devm_* equivalent). + </para> + <para> + When manually registering IRQs, drivers must not set the DRIVER_HAVE_IRQ + driver feature flag, and must not provide the + <methodname>irq_handler</methodname> driver operation. They must set the + <structname>drm_device</structname> <structfield>irq_enabled</structfield> + field to 1 upon registration of the IRQs, and clear it to 0 after + unregistering the IRQs. + </para> + </sect4> + </sect3> + <sect3> + <title>Memory Manager Initialization</title> + <para> + Every DRM driver requires a memory manager which must be initialized at + load time. DRM currently contains two memory managers, the Translation + Table Manager (TTM) and the Graphics Execution Manager (GEM). + This document describes the use of the GEM memory manager only. See + <xref linkend="drm-memory-management"/> for details. + </para> + </sect3> + <sect3> + <title>Miscellaneous Device Configuration</title> + <para> + Another task that may be necessary for PCI devices during configuration + is mapping the video BIOS. On many devices, the VBIOS describes device + configuration, LCD panel timings (if any), and contains flags indicating + device state. Mapping the BIOS can be done using the pci_map_rom() call, + a convenience function that takes care of mapping the actual ROM, + whether it has been shadowed into memory (typically at address 0xc0000) + or exists on the PCI device in the ROM BAR. Note that after the ROM has + been mapped and any necessary information has been extracted, it should + be unmapped; on many devices, the ROM address decoder is shared with + other BARs, so leaving it mapped could cause undesired behaviour like + hangs or memory corruption. + <!--!Fdrivers/pci/rom.c pci_map_rom--> + </para> + </sect3> + </sect2> + <sect2> + <title>Bus-specific Device Registration and PCI Support</title> + <para> + A number of functions are provided to help with device registration. + The functions deal with PCI and platform devices respectively and are + only provided for historical reasons. These are all deprecated and + shouldn't be used in new drivers. Besides that there's a few + helpers for pci drivers. + </para> +!Edrivers/gpu/drm/drm_pci.c +!Edrivers/gpu/drm/drm_platform.c + </sect2> + </sect1> + + <!-- Internals: memory management --> + + <sect1 id="drm-memory-management"> + <title>Memory management</title> + <para> + Modern Linux systems require large amount of graphics memory to store + frame buffers, textures, vertices and other graphics-related data. Given + the very dynamic nature of many of that data, managing graphics memory + efficiently is thus crucial for the graphics stack and plays a central + role in the DRM infrastructure. + </para> + <para> + The DRM core includes two memory managers, namely Translation Table Maps + (TTM) and Graphics Execution Manager (GEM). TTM was the first DRM memory + manager to be developed and tried to be a one-size-fits-them all + solution. It provides a single userspace API to accommodate the need of + all hardware, supporting both Unified Memory Architecture (UMA) devices + and devices with dedicated video RAM (i.e. most discrete video cards). + This resulted in a large, complex piece of code that turned out to be + hard to use for driver development. + </para> + <para> + GEM started as an Intel-sponsored project in reaction to TTM's + complexity. Its design philosophy is completely different: instead of + providing a solution to every graphics memory-related problems, GEM + identified common code between drivers and created a support library to + share it. GEM has simpler initialization and execution requirements than + TTM, but has no video RAM management capabilities and is thus limited to + UMA devices. + </para> + <sect2> + <title>The Translation Table Manager (TTM)</title> + <para> + TTM design background and information belongs here. + </para> + <sect3> + <title>TTM initialization</title> + <warning><para>This section is outdated.</para></warning> + <para> + Drivers wishing to support TTM must fill out a drm_bo_driver + structure. The structure contains several fields with function + pointers for initializing the TTM, allocating and freeing memory, + waiting for command completion and fence synchronization, and memory + migration. See the radeon_ttm.c file for an example of usage. + </para> + <para> + The ttm_global_reference structure is made up of several fields: + </para> + <programlisting> + struct ttm_global_reference { + enum ttm_global_types global_type; + size_t size; + void *object; + int (*init) (struct ttm_global_reference *); + void (*release) (struct ttm_global_reference *); + }; + </programlisting> + <para> + There should be one global reference structure for your memory + manager as a whole, and there will be others for each object + created by the memory manager at runtime. Your global TTM should + have a type of TTM_GLOBAL_TTM_MEM. The size field for the global + object should be sizeof(struct ttm_mem_global), and the init and + release hooks should point at your driver-specific init and + release routines, which probably eventually call + ttm_mem_global_init and ttm_mem_global_release, respectively. + </para> + <para> + Once your global TTM accounting structure is set up and initialized + by calling ttm_global_item_ref() on it, + you need to create a buffer object TTM to + provide a pool for buffer object allocation by clients and the + kernel itself. The type of this object should be TTM_GLOBAL_TTM_BO, + and its size should be sizeof(struct ttm_bo_global). Again, + driver-specific init and release functions may be provided, + likely eventually calling ttm_bo_global_init() and + ttm_bo_global_release(), respectively. Also, like the previous + object, ttm_global_item_ref() is used to create an initial reference + count for the TTM, which will call your initialization function. + </para> + </sect3> + </sect2> + <sect2 id="drm-gem"> + <title>The Graphics Execution Manager (GEM)</title> + <para> + The GEM design approach has resulted in a memory manager that doesn't + provide full coverage of all (or even all common) use cases in its + userspace or kernel API. GEM exposes a set of standard memory-related + operations to userspace and a set of helper functions to drivers, and let + drivers implement hardware-specific operations with their own private API. + </para> + <para> + The GEM userspace API is described in the + <ulink url="http://lwn.net/Articles/283798/"><citetitle>GEM - the Graphics + Execution Manager</citetitle></ulink> article on LWN. While slightly + outdated, the document provides a good overview of the GEM API principles. + Buffer allocation and read and write operations, described as part of the + common GEM API, are currently implemented using driver-specific ioctls. + </para> + <para> + GEM is data-agnostic. It manages abstract buffer objects without knowing + what individual buffers contain. APIs that require knowledge of buffer + contents or purpose, such as buffer allocation or synchronization + primitives, are thus outside of the scope of GEM and must be implemented + using driver-specific ioctls. + </para> + <para> + On a fundamental level, GEM involves several operations: + <itemizedlist> + <listitem>Memory allocation and freeing</listitem> + <listitem>Command execution</listitem> + <listitem>Aperture management at command execution time</listitem> + </itemizedlist> + Buffer object allocation is relatively straightforward and largely + provided by Linux's shmem layer, which provides memory to back each + object. + </para> + <para> + Device-specific operations, such as command execution, pinning, buffer + read & write, mapping, and domain ownership transfers are left to + driver-specific ioctls. + </para> + <sect3> + <title>GEM Initialization</title> + <para> + Drivers that use GEM must set the DRIVER_GEM bit in the struct + <structname>drm_driver</structname> + <structfield>driver_features</structfield> field. The DRM core will + then automatically initialize the GEM core before calling the + <methodname>load</methodname> operation. Behind the scene, this will + create a DRM Memory Manager object which provides an address space + pool for object allocation. + </para> + <para> + In a KMS configuration, drivers need to allocate and initialize a + command ring buffer following core GEM initialization if required by + the hardware. UMA devices usually have what is called a "stolen" + memory region, which provides space for the initial framebuffer and + large, contiguous memory regions required by the device. This space is + typically not managed by GEM, and must be initialized separately into + its own DRM MM object. + </para> + </sect3> + <sect3> + <title>GEM Objects Creation</title> + <para> + GEM splits creation of GEM objects and allocation of the memory that + backs them in two distinct operations. + </para> + <para> + GEM objects are represented by an instance of struct + <structname>drm_gem_object</structname>. Drivers usually need to extend + GEM objects with private information and thus create a driver-specific + GEM object structure type that embeds an instance of struct + <structname>drm_gem_object</structname>. + </para> + <para> + To create a GEM object, a driver allocates memory for an instance of its + specific GEM object type and initializes the embedded struct + <structname>drm_gem_object</structname> with a call to + <function>drm_gem_object_init</function>. The function takes a pointer to + the DRM device, a pointer to the GEM object and the buffer object size + in bytes. + </para> + <para> + GEM uses shmem to allocate anonymous pageable memory. + <function>drm_gem_object_init</function> will create an shmfs file of + the requested size and store it into the struct + <structname>drm_gem_object</structname> <structfield>filp</structfield> + field. The memory is used as either main storage for the object when the + graphics hardware uses system memory directly or as a backing store + otherwise. + </para> + <para> + Drivers are responsible for the actual physical pages allocation by + calling <function>shmem_read_mapping_page_gfp</function> for each page. + Note that they can decide to allocate pages when initializing the GEM + object, or to delay allocation until the memory is needed (for instance + when a page fault occurs as a result of a userspace memory access or + when the driver needs to start a DMA transfer involving the memory). + </para> + <para> + Anonymous pageable memory allocation is not always desired, for instance + when the hardware requires physically contiguous system memory as is + often the case in embedded devices. Drivers can create GEM objects with + no shmfs backing (called private GEM objects) by initializing them with + a call to <function>drm_gem_private_object_init</function> instead of + <function>drm_gem_object_init</function>. Storage for private GEM + objects must be managed by drivers. + </para> + <para> + Drivers that do not need to extend GEM objects with private information + can call the <function>drm_gem_object_alloc</function> function to + allocate and initialize a struct <structname>drm_gem_object</structname> + instance. The GEM core will call the optional driver + <methodname>gem_init_object</methodname> operation after initializing + the GEM object with <function>drm_gem_object_init</function>. + <synopsis>int (*gem_init_object) (struct drm_gem_object *obj);</synopsis> + </para> + <para> + No alloc-and-init function exists for private GEM objects. + </para> + </sect3> + <sect3> + <title>GEM Objects Lifetime</title> + <para> + All GEM objects are reference-counted by the GEM core. References can be + acquired and release by <function>calling drm_gem_object_reference</function> + and <function>drm_gem_object_unreference</function> respectively. The + caller must hold the <structname>drm_device</structname> + <structfield>struct_mutex</structfield> lock. As a convenience, GEM + provides the <function>drm_gem_object_reference_unlocked</function> and + <function>drm_gem_object_unreference_unlocked</function> functions that + can be called without holding the lock. + </para> + <para> + When the last reference to a GEM object is released the GEM core calls + the <structname>drm_driver</structname> + <methodname>gem_free_object</methodname> operation. That operation is + mandatory for GEM-enabled drivers and must free the GEM object and all + associated resources. + </para> + <para> + <synopsis>void (*gem_free_object) (struct drm_gem_object *obj);</synopsis> + Drivers are responsible for freeing all GEM object resources, including + the resources created by the GEM core. If an mmap offset has been + created for the object (in which case + <structname>drm_gem_object</structname>::<structfield>map_list</structfield>::<structfield>map</structfield> + is not NULL) it must be freed by a call to + <function>drm_gem_free_mmap_offset</function>. The shmfs backing store + must be released by calling <function>drm_gem_object_release</function> + (that function can safely be called if no shmfs backing store has been + created). + </para> + </sect3> + <sect3> + <title>GEM Objects Naming</title> + <para> + Communication between userspace and the kernel refers to GEM objects + using local handles, global names or, more recently, file descriptors. + All of those are 32-bit integer values; the usual Linux kernel limits + apply to the file descriptors. + </para> + <para> + GEM handles are local to a DRM file. Applications get a handle to a GEM + object through a driver-specific ioctl, and can use that handle to refer + to the GEM object in other standard or driver-specific ioctls. Closing a + DRM file handle frees all its GEM handles and dereferences the + associated GEM objects. + </para> + <para> + To create a handle for a GEM object drivers call + <function>drm_gem_handle_create</function>. The function takes a pointer + to the DRM file and the GEM object and returns a locally unique handle. + When the handle is no longer needed drivers delete it with a call to + <function>drm_gem_handle_delete</function>. Finally the GEM object + associated with a handle can be retrieved by a call to + <function>drm_gem_object_lookup</function>. + </para> + <para> + Handles don't take ownership of GEM objects, they only take a reference + to the object that will be dropped when the handle is destroyed. To + avoid leaking GEM objects, drivers must make sure they drop the + reference(s) they own (such as the initial reference taken at object + creation time) as appropriate, without any special consideration for the + handle. For example, in the particular case of combined GEM object and + handle creation in the implementation of the + <methodname>dumb_create</methodname> operation, drivers must drop the + initial reference to the GEM object before returning the handle. + </para> + <para> + GEM names are similar in purpose to handles but are not local to DRM + files. They can be passed between processes to reference a GEM object + globally. Names can't be used directly to refer to objects in the DRM + API, applications must convert handles to names and names to handles + using the DRM_IOCTL_GEM_FLINK and DRM_IOCTL_GEM_OPEN ioctls + respectively. The conversion is handled by the DRM core without any + driver-specific support. + </para> + <para> + GEM also supports buffer sharing with dma-buf file descriptors through + PRIME. GEM-based drivers must use the provided helpers functions to + implement the exporting and importing correctly. See <xref linkend="drm-prime-support" />. + Since sharing file descriptors is inherently more secure than the + easily guessable and global GEM names it is the preferred buffer + sharing mechanism. Sharing buffers through GEM names is only supported + for legacy userspace. Furthermore PRIME also allows cross-device + buffer sharing since it is based on dma-bufs. + </para> + </sect3> + <sect3 id="drm-gem-objects-mapping"> + <title>GEM Objects Mapping</title> + <para> + Because mapping operations are fairly heavyweight GEM favours + read/write-like access to buffers, implemented through driver-specific + ioctls, over mapping buffers to userspace. However, when random access + to the buffer is needed (to perform software rendering for instance), + direct access to the object can be more efficient. + </para> + <para> + The mmap system call can't be used directly to map GEM objects, as they + don't have their own file handle. Two alternative methods currently + co-exist to map GEM objects to userspace. The first method uses a + driver-specific ioctl to perform the mapping operation, calling + <function>do_mmap</function> under the hood. This is often considered + dubious, seems to be discouraged for new GEM-enabled drivers, and will + thus not be described here. + </para> + <para> + The second method uses the mmap system call on the DRM file handle. + <synopsis>void *mmap(void *addr, size_t length, int prot, int flags, int fd, + off_t offset);</synopsis> + DRM identifies the GEM object to be mapped by a fake offset passed + through the mmap offset argument. Prior to being mapped, a GEM object + must thus be associated with a fake offset. To do so, drivers must call + <function>drm_gem_create_mmap_offset</function> on the object. The + function allocates a fake offset range from a pool and stores the + offset divided by PAGE_SIZE in + <literal>obj->map_list.hash.key</literal>. Care must be taken not to + call <function>drm_gem_create_mmap_offset</function> if a fake offset + has already been allocated for the object. This can be tested by + <literal>obj->map_list.map</literal> being non-NULL. + </para> + <para> + Once allocated, the fake offset value + (<literal>obj->map_list.hash.key << PAGE_SHIFT</literal>) + must be passed to the application in a driver-specific way and can then + be used as the mmap offset argument. + </para> + <para> + |
