DRM Internals¶
This chapter documents DRM internals relevant to driver authors and developers working to add support for the latest features to existing drivers.
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.
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.
Driver Initialization¶
At the core of every DRM driver is a struct drm_driver
structure. Drivers typically statically initialize
a drm_driver structure, and then pass it to
drm_dev_alloc()
to allocate a device instance. After the
device instance is fully initialized it can be registered (which makes
it accessible from userspace) using drm_dev_register()
.
The struct drm_driver
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 struct
drm_driver
static information fields, and will
then describe individual operations in details as they get used in later
sections.
Driver Information¶
Driver Features¶
Drivers inform the DRM core about their requirements and supported
features by setting appropriate flags in the driver_features field.
Since those flags influence the DRM core behaviour since registration
time, most of them must be set to registering the struct
drm_driver
instance.
u32 driver_features;
- DRIVER_USE_AGP
- Driver uses AGP interface, the DRM core will manage AGP resources.
- DRIVER_LEGACY
- Denote a legacy driver using shadow attach. Don’t use.
- DRIVER_KMS_LEGACY_CONTEXT
- Used only by nouveau for backwards compatibility with existing userspace. Don’t use.
- DRIVER_PCI_DMA
- Driver is capable of PCI DMA, mapping of PCI DMA buffers to userspace will be enabled. Deprecated.
- DRIVER_SG
- Driver can perform scatter/gather DMA, allocation and mapping of scatter/gather buffers will be enabled. Deprecated.
- DRIVER_HAVE_DMA
- Driver supports DMA, the userspace DMA API will be supported. Deprecated.
- DRIVER_HAVE_IRQ; DRIVER_IRQ_SHARED
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 ?.
DRIVER_IRQ_SHARED indicates whether the device & handler support shared IRQs (note that this is required of PCI drivers).
- DRIVER_GEM
- Driver use the GEM memory manager.
- DRIVER_MODESET
- Driver supports mode setting interfaces (KMS).
- DRIVER_PRIME
- Driver implements DRM PRIME buffer sharing.
- DRIVER_RENDER
- Driver supports dedicated render nodes.
- DRIVER_ATOMIC
- 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.
Major, Minor and Patchlevel¶
int major; int minor; int patchlevel; 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.
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.
Name, Description and Date¶
char *name; char *desc; char *date; The driver name is printed to the kernel log at initialization time, used for IRQ registration and passed to userspace through DRM_IOCTL_VERSION.
The driver description is a purely informative string passed to userspace through the DRM_IOCTL_VERSION ioctl and otherwise unused by the kernel.
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.
Device Instance and Driver Handling¶
A device instance for a drm driver is represented by struct drm_device
. This
is allocated with drm_dev_alloc()
, usually from bus-specific ->:c:func:probe()
callbacks implemented by the driver. The driver then needs to initialize all
the various subsystems for the drm device like memory management, vblank
handling, modesetting support and intial output configuration plus obviously
initialize all the corresponding hardware bits. An important part of this is
also calling drm_dev_set_unique()
to set the userspace-visible unique name of
this device instance. Finally when everything is up and running and ready for
userspace the device instance can be published using drm_dev_register()
.
There is also deprecated support for initalizing device instances using bus-specific helpers and the ->:c:func:load() callback. But due to backwards-compatibility needs the device instance have to be published too early, which requires unpretty global locking to make safe and is therefore only support for existing drivers not yet converted to the new scheme.
When cleaning up a device instance everything needs to be done in reverse:
First unpublish the device instance with drm_dev_unregister()
. Then clean up
any other resources allocated at device initialization and drop the driver’s
reference to drm_device
using drm_dev_unref()
.
Note that the lifetime rules for drm_device
instance has still a lot of
historical baggage. Hence use the reference counting provided by
drm_dev_ref()
and drm_dev_unref()
only carefully.
Also note that embedding of drm_device
is currently not (yet) supported (but
it would be easy to add). Drivers can store driver-private data in the
dev_priv field of drm_device
.
-
void
drm_put_dev
(struct drm_device * dev)¶ Unregister and release a DRM device
Parameters
struct drm_device * dev
- DRM device
Description
Called at module unload time or when a PCI device is unplugged.
Cleans up all DRM device, calling drm_lastclose()
.
Note
Use of this function is deprecated. It will eventually go away
completely. Please use drm_dev_unregister()
and drm_dev_unref()
explicitly
instead to make sure that the device isn’t userspace accessible any more
while teardown is in progress, ensuring that userspace can’t access an
inconsistent state.
-
int
drm_dev_init
(struct drm_device * dev, struct drm_driver * driver, struct device * parent)¶ Initialise new DRM device
Parameters
struct drm_device * dev
- DRM device
struct drm_driver * driver
- DRM driver
struct device * parent
- Parent device object
Description
Initialize a new DRM device. No device registration is done.
Call drm_dev_register()
to advertice the device to user space and register it
with other core subsystems. This should be done last in the device
initialization sequence to make sure userspace can’t access an inconsistent
state.
The initial ref-count of the object is 1. Use drm_dev_ref()
and
drm_dev_unref()
to take and drop further ref-counts.
Note that for purely virtual devices parent can be NULL.
Drivers that do not want to allocate their own device struct
embedding struct drm_device
can call drm_dev_alloc()
instead.
Return
0 on success, or error code on failure.
-
struct drm_device *
drm_dev_alloc
(struct drm_driver * driver, struct device * parent)¶ Allocate new DRM device
Parameters
struct drm_driver * driver
- DRM driver to allocate device for
struct device * parent
- Parent device object
Description
Allocate and initialize a new DRM device. No device registration is done.
Call drm_dev_register()
to advertice the device to user space and register it
with other core subsystems. This should be done last in the device
initialization sequence to make sure userspace can’t access an inconsistent
state.
The initial ref-count of the object is 1. Use drm_dev_ref()
and
drm_dev_unref()
to take and drop further ref-counts.
Note that for purely virtual devices parent can be NULL.
Drivers that wish to subclass or embed struct drm_device
into their
own struct should look at using drm_dev_init()
instead.
Return
Pointer to new DRM device, or ERR_PTR on failure.
-
void
drm_dev_ref
(struct drm_device * dev)¶ Take reference of a DRM device
Parameters
struct drm_device * dev
- device to take reference of or NULL
Description
This increases the ref-count of dev by one. You must already own a
reference when calling this. Use drm_dev_unref()
to drop this reference
again.
This function never fails. However, this function does not provide any guarantee whether the device is alive or running. It only provides a reference to the object and the memory associated with it.
-
void
drm_dev_unref
(struct drm_device * dev)¶ Drop reference of a DRM device
Parameters
struct drm_device * dev
- device to drop reference of or NULL
Description
This decreases the ref-count of dev by one. The device is destroyed if the ref-count drops to zero.
-
int
drm_dev_register
(struct drm_device * dev, unsigned long flags)¶ Register DRM device
Parameters
struct drm_device * dev
- Device to register
unsigned long flags
- Flags passed to the driver’s .:c:func:load() function
Description
Register the DRM device dev with the system, advertise device to user-space
and start normal device operation. dev must be allocated via drm_dev_alloc()
previously.
Never call this twice on any device!
NOTE
To ensure backward compatibility with existing drivers method this
function calls the ->:c:func:load() method after registering the device nodes,
creating race conditions. Usage of the ->:c:func:load() methods is therefore
deprecated, drivers must perform all initialization before calling
drm_dev_register()
.
Return
0 on success, negative error code on failure.
-
void
drm_dev_unregister
(struct drm_device * dev)¶ Unregister DRM device
Parameters
struct drm_device * dev
- Device to unregister
Description
Unregister the DRM device from the system. This does the reverse of
drm_dev_register()
but does not deallocate the device. The caller must call
drm_dev_unref()
to drop their final reference.
This should be called first in the device teardown code to make sure userspace can’t access the device instance any more.
-
int
drm_dev_set_unique
(struct drm_device * dev, const char * name)¶ Set the unique name of a DRM device
Parameters
struct drm_device * dev
- device of which to set the unique name
const char * name
- unique name
Description
Sets the unique name of a DRM device using the specified string. Drivers can use this at driver probe time if the unique name of the devices they drive is static.
Return
0 on success or a negative error code on failure.
-
struct
drm_driver
¶ DRM driver structure
Definition
struct drm_driver {
u32 (* get_vblank_counter) (struct drm_device *dev, unsigned int pipe);
int (* enable_vblank) (struct drm_device *dev, unsigned int pipe);
void (* disable_vblank) (struct drm_device *dev, unsigned int pipe);
int (* device_is_agp) (struct drm_device *dev);
int (* get_scanout_position) (struct drm_device *dev, unsigned int pipe,unsigned int flags, int *vpos, int *hpos,ktime_t *stime, ktime_t *etime,const struct drm_display_mode *mode);
int (* get_vblank_timestamp) (struct drm_device *dev, unsigned int pipe,int *max_error,struct timeval *vblank_time,unsigned flags);
int (* master_create) (struct drm_device *dev, struct drm_master *master);
void (* master_destroy) (struct drm_device *dev, struct drm_master *master);
int (* master_set) (struct drm_device *dev, struct drm_file *file_priv,bool from_open);
void (* master_drop) (struct drm_device *dev, struct drm_file *file_priv);
void (* gem_free_object) (struct drm_gem_object *obj);
void (* gem_free_object_unlocked) (struct drm_gem_object *obj);
struct drm_gem_object *(* gem_create_object) (struct drm_device *dev,size_t size);
int (* dumb_create) (struct drm_file *file_priv,struct drm_device *dev,struct drm_mode_create_dumb *args);
int (* dumb_map_offset) (struct drm_file *file_priv,struct drm_device *dev, uint32_t handle,uint64_t *offset);
int (* dumb_destroy) (struct drm_file *file_priv,struct drm_device *dev,uint32_t handle);
};
Members
get_vblank_counter
Driver callback for fetching a raw hardware vblank counter for the CRTC specified with the pipe argument. If a device doesn’t have a hardware counter, the driver can simply use
drm_vblank_no_hw_counter()
function. The DRM core will account for missed vblank events while interrupts where disabled based on system timestamps.Wraparound handling and loss of events due to modesetting is dealt with in the DRM core code, as long as drivers call
drm_crtc_vblank_off()
anddrm_crtc_vblank_on()
when disabling or enabling a CRTC.Returns:
Raw vblank counter value.
enable_vblank
Enable vblank interrupts for the CRTC specified with the pipe argument.
Returns:
Zero on success, appropriate errno if the given crtc‘s vblank interrupt cannot be enabled.
disable_vblank
- Disable vblank interrupts for the CRTC specified with the pipe argument.
device_is_agp
Called by
drm_device_is_agp()
. Typically used to determine if a card is really attached to AGP or not.Returns:
One of three values is returned depending on whether or not the card is absolutely not AGP (return of 0), absolutely is AGP (return of 1), or may or may not be AGP (return of 2).
get_scanout_position
Called by vblank timestamping code.
Returns the current display scanout position from a crtc, and an optional accurate
ktime_get()
timestamp of when position was measured. Note that this is a helper callback which is only used if a driver usesdrm_calc_vbltimestamp_from_scanoutpos()
for the get_vblank_timestamp callback.Parameters:
- dev:
- DRM device.
- pipe:
- Id of the crtc to query.
- flags:
- Flags from the caller (DRM_CALLED_FROM_VBLIRQ or 0).
- vpos:
- Target location for current vertical scanout position.
- hpos:
- Target location for current horizontal scanout position.
- stime:
- Target location for timestamp taken immediately before scanout position query. Can be NULL to skip timestamp.
- etime:
- Target location for timestamp taken immediately after scanout position query. Can be NULL to skip timestamp.
- mode:
- Current display timings.
Returns vpos as a positive number while in active scanout area. Returns vpos as a negative number inside vblank, counting the number of scanlines to go until end of vblank, e.g., -1 means “one scanline until start of active scanout / end of vblank.”
Returns:
Flags, or’ed together as follows:
- DRM_SCANOUTPOS_VALID:
- Query successful.
- DRM_SCANOUTPOS_INVBL:
- Inside vblank.
- DRM_SCANOUTPOS_ACCURATE: Returned position is accurate. A lack of
- this flag means that returned position may be offset by a constant but unknown small number of scanlines wrt. real scanout position.
get_vblank_timestamp
Called by
drm_get_last_vbltimestamp()
. Should return a precise timestamp when the most recent VBLANK interval ended or will end.Specifically, the timestamp in vblank_time should correspond as closely as possible to the time when the first video scanline of the video frame after the end of VBLANK will start scanning out, the time immediately after end of the VBLANK interval. If the crtc is currently inside VBLANK, this will be a time in the future. If the crtc is currently scanning out a frame, this will be the past start time of the current scanout. This is meant to adhere to the OpenML OML_sync_control extension specification.
Paramters:
- dev:
- dev DRM device handle.
- pipe:
- crtc for which timestamp should be returned.
- max_error:
- Maximum allowable timestamp error in nanoseconds. Implementation should strive to provide timestamp with an error of at most max_error nanoseconds. Returns true upper bound on error for timestamp.
- vblank_time:
- Target location for returned vblank timestamp.
- flags:
- 0 = Defaults, no special treatment needed. DRM_CALLED_FROM_VBLIRQ = Function is called from vblank irq handler. Some drivers need to apply some workarounds for gpu-specific vblank irq quirks if flag is set.
Returns:
Zero if timestamping isn’t supported in current display mode or a negative number on failure. A positive status code on success, which describes how the vblank_time timestamp was computed.
master_create
- Called whenever a new master is created. Only used by vmwgfx.
master_destroy
- Called whenever a master is destroyed. Only used by vmwgfx.
master_set
- Called whenever the minor master is set. Only used by vmwgfx.
master_drop
- Called whenever the minor master is dropped. Only used by vmwgfx.
gem_free_object
deconstructor for drm_gem_objects
This is deprecated and should not be used by new drivers. Use gem_free_object_unlocked instead.
gem_free_object_unlocked
deconstructor for drm_gem_objects
This is for drivers which are not encumbered with dev->struct_mutex legacy locking schemes. Use this hook instead of gem_free_object.
gem_create_object
constructor for gem objects
Hook for allocating the GEM object struct, for use by core helpers.
dumb_create
This creates a new dumb buffer in the driver’s backing storage manager (GEM, TTM or something else entirely) and returns the resulting buffer handle. This handle can then be wrapped up into a framebuffer modeset object.
Note that userspace is not allowed to use such objects for render acceleration - drivers must create their own private ioctls for such a use case.
Width, height and depth are specified in the
drm_mode_create_dumb
argument. The callback needs to fill the handle, pitch and size for the created buffer.Called by the user via ioctl.
Returns:
Zero on success, negative errno on failure.
dumb_map_offset
Allocate an offset in the drm device node’s address space to be able to memory map a dumb buffer. GEM-based drivers must use
drm_gem_create_mmap_offset()
to implement this.Called by the user via ioctl.
Returns:
Zero on success, negative errno on failure.
dumb_destroy
This destroys the userspace handle for the given dumb backing storage buffer. Since buffer objects must be reference counted in the kernel a buffer object won’t be immediately freed if a framebuffer modeset object still uses it.
Called by the user via ioctl.
Returns:
Zero on success, negative errno on failure.
Description
This structure represent the common code for a family of cards. There will
one drm_device for each card present in this family. It contains lots of
vfunc entries, and a pile of those probably should be moved to more
appropriate places like drm_mode_config_funcs
or into a new operations
structure for GEM drivers.
Driver Load¶
IRQ Registration¶
The DRM core tries to facilitate IRQ handler registration and
unregistration by providing drm_irq_install()
and
drm_irq_uninstall()
functions. Those functions only
support a single interrupt per device, devices that use more than one
IRQs need to be handled manually.
Managed IRQ Registration¶
drm_irq_install()
starts by calling the irq_preinstall
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.
The passed-in IRQ will then be requested by a call to
request_irq()
. If the DRIVER_IRQ_SHARED driver feature
flag is set, a shared (IRQF_SHARED) IRQ handler will be requested.
The IRQ handler function must be provided as the mandatory irq_handler
driver operation. It will get passed directly to
request_irq()
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.
Finally the function calls the optional irq_postinstall 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.
drm_irq_uninstall()
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
irq_uninstall driver operation. The operation must disable all hardware
interrupts. Finally the function frees the IRQ by calling
free_irq()
.
Manual IRQ Registration¶
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 request_irq()
and
free_irq()
functions, or their devm_request_irq()
and
devm_free_irq()
equivalents).
When manually registering IRQs, drivers must not set the
DRIVER_HAVE_IRQ driver feature flag, and must not provide the
irq_handler driver operation. They must set the struct
drm_device
irq_enabled field to 1 upon
registration of the IRQs, and clear it to 0 after unregistering the
IRQs.
Memory Manager Initialization¶
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 ? for details.
Miscellaneous Device Configuration¶
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.
Bus-specific Device Registration and PCI Support¶
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.
-
drm_dma_handle_t *
drm_pci_alloc
(struct drm_device * dev, size_t size, size_t align)¶ Allocate a PCI consistent memory block, for DMA.
Parameters
struct drm_device * dev
- DRM device
size_t size
- size of block to allocate
size_t align
- alignment of block
Return
A handle to the allocated memory block on success or NULL on failure.
-
void
drm_pci_free
(struct drm_device * dev, drm_dma_handle_t * dmah)¶ Free a PCI consistent memory block
Parameters
struct drm_device * dev
- DRM device
drm_dma_handle_t * dmah
- handle to memory block
-
int
drm_get_pci_dev
(struct pci_dev * pdev, const struct pci_device_id * ent, struct drm_driver * driver)¶ Register a PCI device with the DRM subsystem
Parameters
struct pci_dev * pdev
- PCI device
const struct pci_device_id * ent
- entry from the PCI ID table that matches pdev
struct drm_driver * driver
- DRM device driver
Description
Attempt to gets inter module “drm” information. If we are first then register the character device and inter module information. Try and register, if we fail to register, backout previous work.
NOTE
This function is deprecated, please use drm_dev_alloc()
and
drm_dev_register()
instead and remove your ->:c:func:load() callback.
Return
0 on success or a negative error code on failure.
-
int
drm_pci_init
(struct drm_driver * driver, struct pci_driver * pdriver)¶ Register matching PCI devices with the DRM subsystem
Parameters
struct drm_driver * driver
- DRM device driver
struct pci_driver * pdriver
- PCI device driver
Description
Initializes a drm_device structures, registering the stubs and initializing the AGP device.
NOTE
This function is deprecated. Modern modesetting drm drivers should use
pci_register_driver()
directly, this function only provides shadow-binding
support for old legacy drivers on top of that core pci function.
Return
0 on success or a negative error code on failure.
-
void
drm_pci_exit
(struct drm_driver * driver, struct pci_driver * pdriver)¶ Unregister matching PCI devices from the DRM subsystem
Parameters
struct drm_driver * driver
- DRM device driver
struct pci_driver * pdriver
- PCI device driver
Description
Unregisters one or more devices matched by a PCI driver from the DRM subsystem.
NOTE
This function is deprecated. Modern modesetting drm drivers should use
pci_unregister_driver()
directly, this function only provides shadow-binding
support for old legacy drivers on top of that core pci function.
-
int
drm_platform_init
(struct drm_driver * driver, struct platform_device * platform_device)¶ Register a platform device with the DRM subsystem
Parameters
struct drm_driver * driver
- DRM device driver
struct platform_device * platform_device
- platform device to register
Description
Registers the specified DRM device driver and platform device with the DRM subsystem, initializing a drm_device structure and calling the driver’s .:c:func:load() function.
NOTE
This function is deprecated, please use drm_dev_alloc()
and
drm_dev_register()
instead and remove your ->:c:func:load() callback.
Return
0 on success or a negative error code on failure.
Open/Close, File Operations and IOCTLs¶
Open and Close¶
Open and close handlers. None of those methods are mandatory:
int (*firstopen) (struct drm_device *);
void (*lastclose) (struct drm_device *);
int (*open) (struct drm_device *, struct drm_file *);
void (*preclose) (struct drm_device *, struct drm_file *);
void (*postclose) (struct drm_device *, struct drm_file *);
The firstopen method is called by the DRM core for legacy UMS (User Mode Setting) drivers only when an application opens a device that has no other opened file handle. UMS drivers can implement it to acquire device resources. KMS drivers can’t use the method and must acquire resources in the load method instead.
Similarly the lastclose method is called when the last application holding a file handle opened on the device closes it, for both UMS and KMS drivers. Additionally, the method is also called at module unload time or, for hot-pluggable devices, when the device is unplugged. The firstopen and lastclose calls can thus be unbalanced.
The open method is called every time the device is opened by an
application. Drivers can allocate per-file private data in this method
and store them in the struct struct drm_file
driver_priv field. Note that the open method is
called before firstopen.
The close operation is split into preclose and postclose methods. Drivers must stop and cleanup all per-file operations in the preclose method. For instance pending vertical blanking and page flip events must be cancelled. No per-file operation is allowed on the file handle after returning from the preclose method.
Finally the postclose method is called as the last step of the close operation, right before calling the lastclose method if no other open file handle exists for the device. Drivers that have allocated per-file private data in the open method should free it here.
The lastclose method should restore CRTC and plane properties to default value, so that a subsequent open of the device will not inherit state from the previous user. It can also be used to execute delayed power switching state changes, e.g. in conjunction with the VGA Switcheroo infrastructure. Beyond that KMS drivers should not do any further cleanup. Only legacy UMS drivers might need to clean up device state so that the vga console or an independent fbdev driver could take over.
File Operations¶
Drivers must define the file operations structure that forms the DRM
userspace API entry point, even though most of those operations are
implemented in the DRM core. The mandatory functions are drm_open()
,
drm_read()
, drm_ioctl()
and drm_compat_ioctl()
if CONFIG_COMPAT is enabled
(note that drm_compat_ioctl will be NULL if CONFIG_COMPAT=n). Drivers which
implement private ioctls that require 32/64 bit compatibility support must
provide their own .:c:func:compat_ioctl() handler that processes private ioctls and
calls drm_compat_ioctl()
for core ioctls.
In addition drm_read()
and drm_poll()
provide support for DRM events. DRM
events are a generic and extensible means to send asynchronous events to
userspace through the file descriptor. They are used to send vblank event and
page flip completions by the KMS API. But drivers can also use it for their
own needs, e.g. to signal completion of rendering.
The memory mapping implementation will vary depending on how the driver
manages memory. Legacy drivers will use the deprecated drm_legacy_mmap()
function, modern drivers should use one of the provided memory-manager
specific implementations. For GEM-based drivers this is drm_gem_mmap()
.
No other file operations are supported by the DRM userspace API. Overall the following is an example #file_operations structure:
static const example_drm_fops = {
.owner = THIS_MODULE,
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = drm_ioctl,
.compat_ioctl = drm_compat_ioctl, // NULL if CONFIG_COMPAT=n
.poll = drm_poll,
.read = drm_read,
.llseek = no_llseek,
.mmap = drm_gem_mmap,
};
-
int
drm_open
(struct inode * inode, struct file * filp)¶ open method for DRM file
Parameters
struct inode * inode
- device inode
struct file * filp
- file pointer.
Description
This function must be used by drivers as their .:c:func:open() #file_operations method. It looks up the correct DRM device and instantiates all the per-file resources for it.
Return
0 on success or negative errno value on falure.
-
int
drm_release
(struct inode * inode, struct file * filp)¶ release method for DRM file
Parameters
struct inode * inode
- device inode
struct file * filp
- file pointer.
Description
This function must be used by drivers as their .:c:func:release() #file_operations
method. It frees any resources associated with the open file, and if this is
the last open file for the DRM device also proceeds to call drm_lastclose()
.
Return
Always succeeds and returns 0.
-
ssize_t
drm_read
(struct file * filp, char __user * buffer, size_t count, loff_t * offset)¶ read method for DRM file
Parameters
struct file * filp
- file pointer
char __user * buffer
- userspace destination pointer for the read
size_t count
- count in bytes to read
loff_t * offset
- offset to read
Description
This function must be used by drivers as their .:c:func:read() #file_operations method iff they use DRM events for asynchronous signalling to userspace. Since events are used by the KMS API for vblank and page flip completion this means all modern display drivers must use it.
offset is ignore, DRM events are read like a pipe. Therefore drivers also
must set the .:c:func:llseek() #file_operation to no_llseek()
. Polling support is
provided by drm_poll()
.
This function will only ever read a full event. Therefore userspace must supply a big enough buffer to fit any event to ensure forward progress. Since the maximum event space is currently 4K it’s recommended to just use that for safety.
Return
Number of bytes read (always aligned to full events, and can be 0) or a negative error code on failure.
-
unsigned int
drm_poll
(struct file * filp, struct poll_table_struct * wait)¶ poll method for DRM file
Parameters
struct file * filp
- file pointer
struct poll_table_struct * wait
- poll waiter table
Description
This function must be used by drivers as their .:c:func:read() #file_operations method iff they use DRM events for asynchronous signalling to userspace. Since events are used by the KMS API for vblank and page flip completion this means all modern display drivers must use it.
See also drm_read()
.
Return
Mask of POLL flags indicating the current status of the file.
-
int
drm_event_reserve_init_locked
(struct drm_device * dev, struct drm_file * file_priv, struct drm_pending_event * p, struct drm_event * e)¶ init a DRM event and reserve space for it
Parameters
struct drm_device * dev
- DRM device
struct drm_file * file_priv
- DRM file private data
struct drm_pending_event * p
- tracking structure for the pending event
struct drm_event * e
- actual event data to deliver to userspace
Description
This function prepares the passed in event for eventual delivery. If the event
doesn’t get delivered (because the IOCTL fails later on, before queuing up
anything) then the even must be cancelled and freed using
drm_event_cancel_free()
. Successfully initialized events should be sent out
using drm_send_event()
or drm_send_event_locked()
to signal completion of the
asynchronous event to userspace.
If callers embedded p into a larger structure it must be allocated with kmalloc and p must be the first member element.
This is the locked version of drm_event_reserve_init()
for callers which
already hold dev->event_lock.
Return
0 on success or a negative error code on failure.
-
int
drm_event_reserve_init
(struct drm_device * dev, struct drm_file * file_priv, struct drm_pending_event * p, struct drm_event * e)¶ init a DRM event and reserve space for it
Parameters
struct drm_device * dev
- DRM device
struct drm_file * file_priv
- DRM file private data
struct drm_pending_event * p
- tracking structure for the pending event
struct drm_event * e
- actual event data to deliver to userspace
Description
This function prepares the passed in event for eventual delivery. If the event
doesn’t get delivered (because the IOCTL fails later on, before queuing up
anything) then the even must be cancelled and freed using
drm_event_cancel_free()
. Successfully initialized events should be sent out
using drm_send_event()
or drm_send_event_locked()
to signal completion of the
asynchronous event to userspace.
If callers embedded p into a larger structure it must be allocated with kmalloc and p must be the first member element.
Callers which already hold dev->event_lock should use
drm_event_reserve_init()
instead.
Return
0 on success or a negative error code on failure.
-
void
drm_event_cancel_free
(struct drm_device * dev, struct drm_pending_event * p)¶ free a DRM event and release it’s space
Parameters
struct drm_device * dev
- DRM device
struct drm_pending_event * p
- tracking structure for the pending event
Description
This function frees the event p initialized with drm_event_reserve_init()
and releases any allocated space.
-
void
drm_send_event_locked
(struct drm_device * dev, struct drm_pending_event * e)¶ send DRM event to file descriptor
Parameters
struct drm_device * dev
- DRM device
struct drm_pending_event * e
- DRM event to deliver
Description
This function sends the event e, initialized with drm_event_reserve_init()
,
to its associated userspace DRM file. Callers must already hold
dev->event_lock, see drm_send_event()
for the unlocked version.
Note that the core will take care of unlinking and disarming events when the corresponding DRM file is closed. Drivers need not worry about whether the DRM file for this event still exists and can call this function upon completion of the asynchronous work unconditionally.
-
void
drm_send_event
(struct drm_device * dev, struct drm_pending_event * e)¶ send DRM event to file descriptor
Parameters
struct drm_device * dev
- DRM device
struct drm_pending_event * e
- DRM event to deliver
Description
This function sends the event e, initialized with drm_event_reserve_init()
,
to its associated userspace DRM file. This function acquires dev->event_lock,
see drm_send_event_locked()
for callers which already hold this lock.
Note that the core will take care of unlinking and disarming events when the corresponding DRM file is closed. Drivers need not worry about whether the DRM file for this event still exists and can call this function upon completion of the asynchronous work unconditionally.
IOCTLs¶
- struct drm_ioctl_desc *ioctls; int num_ioctls;
- Driver-specific ioctls descriptors table.
Driver-specific ioctls numbers start at DRM_COMMAND_BASE. The ioctls descriptors table is indexed by the ioctl number offset from the base value. Drivers can use the DRM_IOCTL_DEF_DRV() macro to initialize the table entries.
DRM_IOCTL_DEF_DRV(ioctl, func, flags)
ioctl
is the ioctl name. Drivers must define the DRM_##ioctl and
DRM_IOCTL_##ioctl macros to the ioctl number offset from
DRM_COMMAND_BASE and the ioctl number respectively. The first macro is
private to the device while the second must be exposed to userspace in a
public header.
func
is a pointer to the ioctl handler function compatible with the
drm_ioctl_t
type.
typedef int drm_ioctl_t(struct drm_device *dev, void *data,
struct drm_file *file_priv);
flags
is a bitmask combination of the following values. It restricts
how the ioctl is allowed to be called.
- DRM_AUTH - Only authenticated callers allowed
- DRM_MASTER - The ioctl can only be called on the master file handle
- DRM_ROOT_ONLY - Only callers with the SYSADMIN capability allowed
- DRM_CONTROL_ALLOW - The ioctl can only be called on a control device
- DRM_UNLOCKED - The ioctl handler will be called without locking the DRM global mutex. This is the enforced default for kms drivers (i.e. using the DRIVER_MODESET flag) and hence shouldn’t be used any more for new drivers.
-
int
drm_noop
(struct drm_device * dev, void * data, struct drm_file * file_priv)¶ DRM no-op ioctl implemntation
Parameters
struct drm_device * dev
- DRM device for the ioctl
void * data
- data pointer for the ioctl
struct drm_file * file_priv
- DRM file for the ioctl call
Description
This no-op implementation for drm ioctls is useful for deprecated functionality where we can’t return a failure code because existing userspace checks the result of the ioctl, but doesn’t care about the action.
Always returns successfully with 0.
-
int
drm_invalid_op
(struct drm_device * dev, void * data, struct drm_file * file_priv)¶ DRM invalid ioctl implemntation
Parameters
struct drm_device * dev
- DRM device for the ioctl
void * data
- data pointer for the ioctl
struct drm_file * file_priv
- DRM file for the ioctl call
Description
This no-op implementation for drm ioctls is useful for deprecated functionality where we really don’t want to allow userspace to call the ioctl any more. This is the case for old ums interfaces for drivers that transitioned to kms gradually and so kept the old legacy tables around. This only applies to radeon and i915 kms drivers, other drivers shouldn’t need to use this function.
Always fails with a return value of -EINVAL.
-
long
drm_ioctl
(struct file * filp, unsigned int cmd, unsigned long arg)¶ ioctl callback implementation for DRM drivers
Parameters
struct file * filp
- file this ioctl is called on
unsigned int cmd
- ioctl cmd number
unsigned long arg
- user argument
Description
Looks up the ioctl function in the ::ioctls table, checking for root previleges if so required, and dispatches to the respective function.
Return
Zero on success, negative error code on failure.
-
bool
drm_ioctl_flags
(unsigned int nr, unsigned int * flags)¶ Check for core ioctl and return ioctl permission flags
Parameters
unsigned int nr
- ioctl number
unsigned int * flags
- where to return the ioctl permission flags
Description
This ioctl is only used by the vmwgfx driver to augment the access checks done by the drm core and insofar a pretty decent layering violation. This shouldn’t be used by any drivers.
Return
True if the nr corresponds to a DRM core ioctl number, false otherwise.
Misc Utilities¶
Printer¶
A simple wrapper for dev_printk()
, seq_printf()
, etc. Allows same
debug code to be used for both debugfs and printk logging.
For example:
void log_some_info(struct drm_printer *p)
{
drm_printf(p, "foo=``d``\n", foo);
drm_printf(p, "bar=``d``\n", bar);
}
#ifdef CONFIG_DEBUG_FS
void debugfs_show(struct seq_file *f)
{
struct drm_printer p = drm_seq_file_printer(f);
log_some_info(:c:type:`p`);
}
#endif
void some_other_function(...)
{
struct drm_printer p = drm_info_printer(drm->dev);
log_some_info(:c:type:`p`);
}
-
struct
drm_printer
¶ drm output “stream”
Definition
struct drm_printer {
void (* printfn) (struct drm_printer *p, struct va_format *vaf);
void * arg;
};
Members
printfn
- actual output fxn
arg
- output fxn specific data
Description
Do not use struct members directly. Use drm_printer_seq_file()
,
drm_printer_info()
, etc to initialize. And drm_printf()
for output.
-
struct drm_printer
drm_seq_file_printer
(struct seq_file * f)¶ construct a
drm_printer
that outputs toseq_file
Parameters
struct seq_file * f
- the struct
seq_file
to output to
Return
The drm_printer
object
-
struct drm_printer
drm_info_printer
(struct device * dev)¶ construct a
drm_printer
that outputs todev_printk()
Parameters
struct device * dev
- the struct
device
pointer
Return
The drm_printer
object
-
void
drm_printf
(struct drm_printer * p, const char * f, ...)¶ print to a
drm_printer
stream
Parameters
struct drm_printer * p
- the
drm_printer
const char * f
- format string
...
- variable arguments
Legacy Support Code¶
The section very briefly covers some of the old legacy support code which is only used by old DRM drivers which have done a so-called shadow-attach to the underlying device instead of registering as a real driver. This also includes some of the old generic buffer management and command submission code. Do not use any of this in new and modern drivers.
Legacy Suspend/Resume¶
The DRM core provides some suspend/resume code, but drivers wanting full suspend/resume support should provide save() and restore() functions. These are called at suspend, hibernate, or resume time, and should perform any state save or restore required by your device across suspend or hibernate states.
int (*suspend) (struct drm_device *, pm_message_t state); int
(*resume) (struct drm_device *);
Those are legacy suspend and resume methods which only work with the
legacy shadow-attach driver registration functions. New driver should
use the power management interface provided by their bus type (usually
through the struct device_driver
dev_pm_ops) and set these methods to NULL.
Legacy DMA Services¶
This should cover how DMA mapping etc. is supported by the core. These functions are deprecated and should not be used.