DRM Internals

This chapter documents DRM internals relevant to driver authors anddevelopers working to add support for the latest features to existingdrivers.

First, we go over some typical driver initialization requirements, likesetting up command buffers, creating an initial output configuration,and initializing core services. Subsequent sections cover core internalsin more detail, providing implementation notes and examples.

The DRM layer provides several services to graphics drivers, many ofthem driven by the application interfaces it provides through libdrm,the library that wraps most of the DRM ioctls. These include vblankevent handling, memory management, output management, framebuffermanagement, command submission & fencing, suspend/resume support, andDMA services.

Driver Initialization

At the core of every DRM driver is astructdrm_driver structure. Drivers typically statically initializea drm_driver structure, and then pass it todrm_dev_alloc() to allocate a device instance. After thedevice instance is fully initialized it can be registered (which makesit accessible from userspace) usingdrm_dev_register().

Thestructdrm_driver structurecontains static information that describes the driver and features itsupports, and pointers to methods that the DRM core will call toimplement the DRM API. We will first go through thestructdrm_driver static information fields, and willthen describe individual operations in details as they get used in latersections.

Driver Information

Major, Minor and Patchlevel

int major; int minor; int patchlevel;The DRM core identifies driver versions by a major, minor and patchlevel triplet. The information is printed to the kernel log atinitialization time and passed to userspace through theDRM_IOCTL_VERSION ioctl.

The major and minor numbers are also used to verify the requested driverAPI version passed to DRM_IOCTL_SET_VERSION. When the driver APIchanges between minor versions, applications can callDRM_IOCTL_SET_VERSION to select a specific version of the API. If therequested major isn’t equal to the driver major, or the requested minoris larger than the driver minor, the DRM_IOCTL_SET_VERSION call willreturn an error. Otherwise the driver’sset_version() method will becalled with the requested version.

Name and Description

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 throughDRM_IOCTL_VERSION.

The driver description is a purely informative string passed touserspace through the DRM_IOCTL_VERSION ioctl and otherwise unused bythe kernel.

Module Initialization

This library provides helpers registering DRM drivers during moduleinitialization and shutdown. The provided helpers act like bus-specificmodule helpers, such asmodule_pci_driver(), but respect additionalparameters that control DRM driver registration.

Below is an example of initializing a DRM driver for a device on thePCI bus.

structpci_drivermy_pci_drv={};drm_module_pci_driver(my_pci_drv);

The generated code will test if DRM drivers are enabled and registerthe PCI driver my_pci_drv. For more complex module initialization, youcan still usemodule_init() andmodule_exit() in your driver.

Device Instance and Driver Handling

A device instance for a drm driver is represented bystructdrm_device. Thisis allocated and initialized withdevm_drm_dev_alloc(), usually frombus-specific ->probe() callbacks implemented by the driver. The driver thenneeds to initialize all the various subsystems for the drm device like memorymanagement, vblank handling, modesetting support and initial outputconfiguration plus obviously initialize all the corresponding hardware bits.Finally when everything is up and running and ready for userspace the deviceinstance can be published usingdrm_dev_register().

There is also deprecated support for initializing device instances usingbus-specific helpers and thedrm_driver.load callback. But due tobackwards-compatibility needs the device instance have to be published tooearly, which requires unpretty global locking to make safe and is thereforeonly 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 withdrm_dev_unregister(). Then clean upany other resources allocated at device initialization and drop the driver’sreference todrm_device usingdrm_dev_put().

Note that any allocation or resource which is visible to userspace must bereleased only when the finaldrm_dev_put() is called, and not when thedriver is unbound from the underlying physical structdevice. Best to usedrm_device managed resources withdrmm_add_action(),drmm_kmalloc() andrelated functions.

devres managed resources likedevm_kmalloc() can only be used for resourcesdirectly related to the underlying hardware device, and only used in codepaths fully protected bydrm_dev_enter() anddrm_dev_exit().

Display driver example

The following example shows a typical structure of a DRM display driver.The example focus on theprobe() function and the other functions that isalmost always present and serves as a demonstration ofdevm_drm_dev_alloc().

structdriver_device{structdrm_devicedrm;void*userspace_facing;structclk*pclk;};staticconststructdrm_driverdriver_drm_driver={[...]};staticintdriver_probe(structplatform_device*pdev){structdriver_device*priv;structdrm_device*drm;intret;priv=devm_drm_dev_alloc(&pdev->dev,&driver_drm_driver,structdriver_device,drm);if(IS_ERR(priv))returnPTR_ERR(priv);drm=&priv->drm;ret=drmm_mode_config_init(drm);if(ret)returnret;priv->userspace_facing=drmm_kzalloc(...,GFP_KERNEL);if(!priv->userspace_facing)return-ENOMEM;priv->pclk=devm_clk_get(dev,"PCLK");if(IS_ERR(priv->pclk))returnPTR_ERR(priv->pclk);// Further setup, display pipeline etcplatform_set_drvdata(pdev,drm);drm_mode_config_reset(drm);ret=drm_dev_register(drm);if(ret)returnret;drm_fbdev_{...}_setup(drm,32);return0;}// This function is called before the devm_ resources are releasedstaticintdriver_remove(structplatform_device*pdev){structdrm_device*drm=platform_get_drvdata(pdev);drm_dev_unregister(drm);drm_atomic_helper_shutdown(drm)return0;}// This function is called on kernel restart and shutdownstaticvoiddriver_shutdown(structplatform_device*pdev){drm_atomic_helper_shutdown(platform_get_drvdata(pdev));}staticint__maybe_unuseddriver_pm_suspend(structdevice*dev){returndrm_mode_config_helper_suspend(dev_get_drvdata(dev));}staticint__maybe_unuseddriver_pm_resume(structdevice*dev){drm_mode_config_helper_resume(dev_get_drvdata(dev));return0;}staticconststructdev_pm_opsdriver_pm_ops={SET_SYSTEM_SLEEP_PM_OPS(driver_pm_suspend,driver_pm_resume)};staticstructplatform_driverdriver_driver={.driver={[...].pm=&driver_pm_ops,},.probe=driver_probe,.remove=driver_remove,.shutdown=driver_shutdown,};module_platform_driver(driver_driver);

Drivers that want to support device unplugging (USB, DT overlay unload) shouldusedrm_dev_unplug() instead ofdrm_dev_unregister(). The driver must protectregions that is accessing device resources to prevent use after they’rereleased. This is done usingdrm_dev_enter() anddrm_dev_exit(). There is oneshortcoming however,drm_dev_unplug() marks the drm_device as unplugged beforedrm_atomic_helper_shutdown() is called. This means that if the disable codepaths are protected, they will not run on regular driver module unload,possibly leaving the hardware enabled.

structdrm_wedge_task_info

information about the guilty task of a wedge dev

Definition:

struct drm_wedge_task_info {    pid_t pid;    char comm[TASK_COMM_LEN];};

Members

pid

pid of the task

comm

command name of the task

enumswitch_power_state

power state of drm device

Constants

DRM_SWITCH_POWER_ON

Power state is ON

DRM_SWITCH_POWER_OFF

Power state is OFF

DRM_SWITCH_POWER_CHANGING

Power state is changing

DRM_SWITCH_POWER_DYNAMIC_OFF

Suspended

structdrm_device

DRM device structure

Definition:

struct drm_device {    int if_version;    struct kref ref;    struct device *dev;    struct device *dma_dev;    struct {        struct list_head resources;        void *final_kfree;        spinlock_t lock;    } managed;    const struct drm_driver *driver;    void *dev_private;    struct drm_minor *primary;    struct drm_minor *render;    struct drm_minor *accel;    bool registered;    struct drm_master *master;#ifdef CONFIG_TRANSPARENT_HUGEPAGE;    struct vfsmount *huge_mnt;#endif;    u32 driver_features;    bool unplugged;    struct inode *anon_inode;    char *unique;    struct mutex master_mutex;    atomic_t open_count;    struct mutex filelist_mutex;    struct list_head filelist;    struct list_head filelist_internal;    struct mutex clientlist_mutex;    struct list_head clientlist;    struct list_head client_sysrq_list;    bool vblank_disable_immediate;    struct drm_vblank_crtc *vblank;    spinlock_t vblank_time_lock;    spinlock_t vbl_lock;    u32 max_vblank_count;    struct list_head vblank_event_list;    spinlock_t event_lock;    unsigned int num_crtcs;    struct drm_mode_config mode_config;    struct mutex object_name_lock;    struct idr object_name_idr;    struct drm_vma_offset_manager *vma_offset_manager;    struct drm_vram_mm *vram_mm;    enum switch_power_state switch_power_state;    struct drm_fb_helper *fb_helper;    struct dentry *debugfs_root;};

Members

if_version

Highest interface version set

ref

Object ref-count

dev

Device structure of bus-device

dma_dev

Device for DMA operations. Only required if the devicedevcannot perform DMA by itself. Should be NULL otherwise. Calldrm_dev_dma_dev() to get the DMA device instead of using thisfield directly. Calldrm_dev_set_dma_dev() to set this field.

DRM devices are sometimes bound to virtual devices that cannotperform DMA by themselves. Drivers should set this field to therespective DMA controller.

Devices on USB and other peripheral busses also cannot performDMA by themselves. Thedma_dev field should point the buscontroller that does DMA on behalve of such a device. Requiredfor importing buffers via dma-buf.

If set, the DRM core automatically releases the reference on thedevice.

managed

Managed resources linked to the lifetime of thisdrm_device astracked byref.

driver

DRM driver managing the device

dev_private

DRM driver private data. This is deprecated and should be left set toNULL.

Instead of using this pointer it is recommended that drivers usedevm_drm_dev_alloc() and embed structdrm_device in their largerper-device structure.

primary

Primary node. Drivers should not interact with thisdirectly. debugfs interfaces can be registered withdrm_debugfs_add_file(), and sysfs should be directly added on thehardware (and not character device node)structdevicedev.

render

Render node. Drivers should not interact with this directly ever.Drivers should not expose any additional interfaces in debugfs orsysfs on this node.

accel

Compute Acceleration node

registered

Internally used bydrm_dev_register() anddrm_connector_register().

master

Currently active master for this device.Protected bymaster_mutex

huge_mnt

Huge tmpfs mountpoint used at GEM object initializationdrm_gem_object_init(). Drivers can calldrm_gem_huge_mnt_create() tocreate, mount and use it. The default tmpfs mountpoint (shm_mnt) isused if NULL.

driver_features

per-device driver features

Drivers can clear specific flags here to disallowcertain features on a per-device basis while stillsharing a singlestructdrm_driver instance acrossall devices.

unplugged

Flag to tell if the device has been unplugged.Seedrm_dev_enter() anddrm_dev_is_unplugged().

anon_inode

inode for private address-space

unique

Unique name of the device

master_mutex

Lock fordrm_minor.master anddrm_file.is_master

open_count

Usage counter for outstanding files open,protected by drm_global_mutex

filelist_mutex

Protectsfilelist.

filelist

List of userspace clients, linked throughdrm_file.lhead.

filelist_internal

List of open DRM files for in-kernel clients.Protected byfilelist_mutex.

clientlist_mutex

Protectsclientlist access.

clientlist

List of in-kernel clients. Protected byclientlist_mutex.

client_sysrq_list

Entry into list of devices registered for sysrq. Allows in-kernelclients on this device to handle sysrq keys.

vblank_disable_immediate

If true, vblank interrupt will be disabled immediately when therefcount drops to zero, as opposed to via the vblank disabletimer.

This can be set to true it the hardware has a working vblank counterwith high-precision timestamping (otherwise there are races) and thedriver usesdrm_crtc_vblank_on() anddrm_crtc_vblank_off()appropriately. Also, seemax_vblank_count,drm_crtc_funcs.get_vblank_counter anddrm_vblank_crtc_config.disable_immediate.

vblank

Array of vblank tracking structures, one perstructdrm_crtc. Forhistorical reasons (vblank support predates kernel modesetting) thisis free-standing and not part ofstructdrm_crtc itself. It must beinitialized explicitly by callingdrm_vblank_init().

vblank_time_lock

Protects vblank count and time updates during vblank enable/disable

vbl_lock

Top-level vblank references lock, wraps the low-levelvblank_time_lock.

max_vblank_count

Maximum value of the vblank registers. This value +1 will result in awrap-around of the vblank register. It is used by the vblank core tohandle wrap-arounds.

If set to zero the vblank core will try to guess the elapsed vblanksbetween times when the vblank interrupt is disabled throughhigh-precision timestamps. That approach is suffering from smallraces and imprecision over longer time periods, hence exposing ahardware vblank counter is always recommended.

This is the statically configured device wide maximum. The drivercan instead choose to use a runtime configurable per-crtc valuedrm_vblank_crtc.max_vblank_count, in which casemax_vblank_countmust be left at zero. Seedrm_crtc_set_max_vblank_count() on howto use the per-crtc value.

If non-zero,drm_crtc_funcs.get_vblank_counter must be set.

vblank_event_list

List of vblank events

event_lock

Protectsvblank_event_list and event delivery ingeneral. Seedrm_send_event() anddrm_send_event_locked().

num_crtcs

Number of CRTCs on this device

mode_config

Current mode config

object_name_lock

GEM information

object_name_idr

GEM information

vma_offset_manager

GEM information

vram_mm

VRAM MM memory manager

switch_power_state

Power state of the client.Used by drivers supporting the switcheroo driver.The state is maintained in thevga_switcheroo_client_ops.set_gpu_state callback

fb_helper

Pointer to the fbdev emulation structure.Set bydrm_fb_helper_init() and cleared bydrm_fb_helper_fini().

debugfs_root

Root directory for debugfs files.

Description

This structure represent a complete card thatmay contain multiple heads.

structdevice*drm_dev_dma_dev(structdrm_device*dev)

returns the DMA device for a DRM device

Parameters

structdrm_device*dev

DRM device

Description

Returns the DMA device of the given DRM device. By default, thisthe DRM device’s parent. Seedrm_dev_set_dma_dev().

Return

A DMA-capable device for the DRM device.

enumdrm_driver_feature

feature flags

Constants

DRIVER_GEM

Driver use the GEM memory manager. This should be set for all moderndrivers.

DRIVER_MODESET

Driver supports mode setting interfaces (KMS).

DRIVER_RENDER

Driver supports dedicated render nodes. See also thesection onrender nodes for details.

DRIVER_ATOMIC

Driver supports the full atomic modesetting userspace API. Driverswhich only use atomic internally, but do not support the fulluserspace API (e.g. not all properties converted to atomic, ormulti-plane updates are not guaranteed to be tear-free) should notset this flag.

DRIVER_SYNCOBJ

Driver supportsdrm_syncobj for explicit synchronization of commandsubmission.

DRIVER_SYNCOBJ_TIMELINE

Driver supports the timeline flavor ofdrm_syncobj for explicitsynchronization of command submission.

DRIVER_COMPUTE_ACCEL

Driver supports compute acceleration devices. This flag is mutually exclusive withDRIVER_RENDER andDRIVER_MODESET. Devices that support both graphics and computeacceleration should be handled by two drivers that are connected using auxiliary bus.

DRIVER_GEM_GPUVA

Driver supports user defined GPU VA bindings for GEM objects.

DRIVER_CURSOR_HOTSPOT

Driver supports and requires cursor hotspot information in thecursor plane (e.g. cursor plane has to actually track the mousecursor and the clients are required to set hotspot in order forthe cursor planes to work correctly).

DRIVER_USE_AGP

Set up DRM AGP support, seedrm_agp_init(), the DRM core will manageAGP resources. New drivers don’t need this.

DRIVER_LEGACY

Denote a legacy driver using shadow attach. Do not use.

DRIVER_PCI_DMA

Driver is capable of PCI DMA, mapping of PCI DMA buffers to userspacewill be enabled. Only for legacy drivers. Do not use.

DRIVER_SG

Driver can perform scatter/gather DMA, allocation and mapping ofscatter/gather buffers will be enabled. Only for legacy drivers. Donot use.

DRIVER_HAVE_DMA

Driver supports DMA, the userspace DMA API will be supported. Onlyfor legacy drivers. Do not use.

DRIVER_HAVE_IRQ

Legacy irq support. Only for legacy drivers. Do not use.

Description

Seedrm_driver.driver_features, drm_device.driver_features anddrm_core_check_feature().

structdrm_driver

DRM driver structure

Definition:

struct drm_driver {    int (*load) (struct drm_device *, unsigned long flags);    int (*open) (struct drm_device *, struct drm_file *);    void (*postclose) (struct drm_device *, struct drm_file *);    void (*unload) (struct drm_device *);    void (*release) (struct drm_device *);    void (*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 (*debugfs_init)(struct drm_minor *minor);    struct drm_gem_object *(*gem_create_object)(struct drm_device *dev, size_t size);    int (*prime_handle_to_fd)(struct drm_device *dev, struct drm_file *file_priv, uint32_t handle, uint32_t flags, int *prime_fd);    int (*prime_fd_to_handle)(struct drm_device *dev, struct drm_file *file_priv, int prime_fd, uint32_t *handle);    struct drm_gem_object * (*gem_prime_import)(struct drm_device *dev, struct dma_buf *dma_buf);    struct drm_gem_object *(*gem_prime_import_sg_table)( struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sgt);    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 (*fbdev_probe)(struct drm_fb_helper *fbdev_helper, struct drm_fb_helper_surface_size *sizes);    void (*show_fdinfo)(struct drm_printer *p, struct drm_file *f);    int major;    int minor;    int patchlevel;    char *name;    char *desc;    u32 driver_features;    const struct drm_ioctl_desc *ioctls;    int num_ioctls;    const struct file_operations *fops;};

Members

load

Backward-compatible driver callback to complete initialization stepsafter the driver is registered. For this reason, may suffer fromrace conditions and its use is deprecated for new drivers. It istherefore only supported for existing drivers not yet converted tothe new scheme. Seedevm_drm_dev_alloc() anddrm_dev_register() forproper and race-free way to set up astructdrm_device.

This is deprecated, do not use!

Returns:

Zero on success, non-zero value on failure.

open

Driver callback when a newstructdrm_file is opened. Useful forsetting up driver-private data structures like buffer allocators,execution contexts or similar things. Such driver-private resourcesmust be released again inpostclose.

Since the display/modeset side of DRM can only be owned by exactlyonestructdrm_file (seedrm_file.is_master anddrm_device.master)there should never be a need to set up any modeset related resourcesin this callback. Doing so would be a driver design bug.

Returns:

0 on success, a negative error code on failure, which will bepromoted to userspace as the result of the open() system call.

postclose

One of the driver callbacks when a newstructdrm_file is closed.Useful for tearing down driver-private data structures allocated inopen like buffer allocators, execution contexts or similar things.

Since the display/modeset side of DRM can only be owned by exactlyonestructdrm_file (seedrm_file.is_master anddrm_device.master)there should never be a need to tear down any modeset relatedresources in this callback. Doing so would be a driver design bug.

unload

Reverse the effects of the driver load callback. Ideally,the clean up performed by the driver should happen in thereverse order of the initialization. Similarly to the loadhook, this handler is deprecated and its usage should bedropped in favor of an open-coded teardown function at thedriver layer. Seedrm_dev_unregister() anddrm_dev_put()for the proper way to remove astructdrm_device.

Theunload() hook is called right after unregisteringthe device.

release

Optional callback for destroying device data after the finalreference is released, i.e. the device is being destroyed.

This is deprecated, clean up all memory allocations associated with adrm_device usingdrmm_add_action(),drmm_kmalloc() and relatedmanaged resources functions.

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.

debugfs_init

Allows drivers to create driver-specific debugfs files.

gem_create_object

constructor for gem objects

Hook for allocating the GEM object struct, for use by the CMAand SHMEM GEM helpers. Returns a GEM object on success, or anERR_PTR()-encoded error code otherwise.

prime_handle_to_fd

PRIME export function. Only used by vmwgfx.

prime_fd_to_handle

PRIME import function. Only used by vmwgfx.

gem_prime_import

Import hook for GEM drivers.

This defaults todrm_gem_prime_import() if not set.

gem_prime_import_sg_table

Optional hook used by the PRIME helper functionsdrm_gem_prime_import() respectivelydrm_gem_prime_import_dev().

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. Thishandle can then be wrapped up into a framebuffer modeset object.

Note that userspace is not allowed to use such objects for renderacceleration - drivers must create their own private ioctls for such a usecase.

Width, height and depth are specified in thedrm_mode_create_dumbargument. The callback needs to fill the handle, pitch and size forthe 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 tomemory map a dumb buffer.

The default implementation isdrm_gem_create_mmap_offset(). GEM baseddrivers must not overwrite this.

Called by the user via ioctl.

Returns:

Zero on success, negative errno on failure.

fbdev_probe

Allocates and initialize the fb_info structure for fbdev emulation.Furthermore it also needs to allocate the DRM framebuffer used toback the fbdev.

This callback is mandatory for fbdev support.

Returns:

0 on success ot a negative error code otherwise.

show_fdinfo

Print device specific fdinfo. SeeDRM client usage stats.

major

driver major number

minor

driver minor number

patchlevel

driver patch level

name

driver name

desc

driver description

driver_features

Driver features, seeenumdrm_driver_feature. Drivers can disablesome features on a per-instance basis usingdrm_device.driver_features.

ioctls

Array of driver-private IOCTL description entries. See the chapter onIOCTL support in the userland interfaceschapter for the full details.

num_ioctls

Number of entries inioctls.

fops

File operations for the DRM device node. See the discussion infile operations for in-depth coverage andsome examples.

Description

This structure represent the common code for a family of cards. There will beonestructdrm_device for each card present in this family. It contains lotsof vfunc entries, and a pile of those probably should be moved to moreappropriate places likedrm_mode_config_funcs or into a new operationsstructure for GEM drivers.

devm_drm_dev_alloc

devm_drm_dev_alloc(parent,driver,type,member)

Resource managed allocation of adrm_device instance

Parameters

parent

Parent device object

driver

DRM driver

type

the type of thestructwhich contains structdrm_device

member

the name of thedrm_device withintype.

Description

This allocates and initialize a new DRM device. No device registration is done.Calldrm_dev_register() to advertice the device to user space and register itwith other core subsystems. This should be done last in the deviceinitialization sequence to make sure userspace can’t access an inconsistentstate.

The initial ref-count of the object is 1. Usedrm_dev_get() anddrm_dev_put() to take and drop further ref-counts.

It is recommended that drivers embedstructdrm_device into their own devicestructure.

Note that this manages the lifetime of the resultingdrm_deviceautomatically using devres. The DRM device initialized with this function isautomatically put on driver detach usingdrm_dev_put().

Return

Pointer to new DRM device, or ERR_PTR on failure.

booldrm_dev_is_unplugged(structdrm_device*dev)

is a DRM device unplugged

Parameters

structdrm_device*dev

DRM device

Description

This function can be called to check whether a hotpluggable is unplugged.Unplugging itself is singalled throughdrm_dev_unplug(). If a device isunplugged, these two functions guarantee that any store before callingdrm_dev_unplug() is visible to callers of this function after it completes

WARNING: This function fundamentally races againstdrm_dev_unplug(). It isrecommended that drivers instead use the underlyingdrm_dev_enter() anddrm_dev_exit() function pairs.

booldrm_core_check_all_features(conststructdrm_device*dev,u32features)

check driver feature flags mask

Parameters

conststructdrm_device*dev

DRM device to check

u32features

feature flag(s) mask

Description

This checksdev for driver features, seedrm_driver.driver_features,drm_device.driver_features, and the variousenumdrm_driver_feature flags.

Returns true if all features in thefeatures mask are supported, falseotherwise.

booldrm_core_check_feature(conststructdrm_device*dev,enumdrm_driver_featurefeature)

check driver feature flags

Parameters

conststructdrm_device*dev

DRM device to check

enumdrm_driver_featurefeature

feature flag

Description

This checksdev for driver features, seedrm_driver.driver_features,drm_device.driver_features, and the variousenumdrm_driver_feature flags.

Returns true if thefeature is supported, false otherwise.

booldrm_drv_uses_atomic_modeset(structdrm_device*dev)

check if the driver implementsatomic_commit()

Parameters

structdrm_device*dev

DRM device

Description

This check is useful if drivers do not have DRIVER_ATOMIC set buthave atomic modesetting internally implemented.

voiddrm_put_dev(structdrm_device*dev)

Unregister and release a DRM device

Parameters

structdrm_device*dev

DRM device

Description

Called at module unload time or when a PCI device is unplugged.

Cleans up all DRM device, callingdrm_lastclose().

Note

Use of this function is deprecated. It will eventually go awaycompletely. Please usedrm_dev_unregister() anddrm_dev_put() explicitlyinstead to make sure that the device isn’t userspace accessible any morewhile teardown is in progress, ensuring that userspace can’t access aninconsistent state.

booldrm_dev_enter(structdrm_device*dev,int*idx)

Enter device critical section

Parameters

structdrm_device*dev

DRM device

int*idx

Pointer to index that will be passed to the matchingdrm_dev_exit()

Description

This function marks and protects the beginning of a section that should notbe entered after the device has been unplugged. The section end is markedwithdrm_dev_exit(). Calls to this function can be nested.

Return

True if it is OK to enter the section, false otherwise.

voiddrm_dev_exit(intidx)

Exit device critical section

Parameters

intidx

index returned fromdrm_dev_enter()

Description

This function marks the end of a section that should not be entered afterthe device has been unplugged.

voiddrm_dev_unplug(structdrm_device*dev)

unplug a DRM device

Parameters

structdrm_device*dev

DRM device

Description

This unplugs a hotpluggable DRM device, which makes it inaccessible touserspace operations. Entry-points can usedrm_dev_enter() anddrm_dev_exit() to protect device resources in a race free manner. Thisessentially unregisters the device likedrm_dev_unregister(), but can becalled while there are still open users ofdev.

voiddrm_dev_set_dma_dev(structdrm_device*dev,structdevice*dma_dev)

set the DMA device for a DRM device

Parameters

structdrm_device*dev

DRM device

structdevice*dma_dev

DMA device or NULL

Description

Sets the DMA device of the given DRM device. Only required ifthe DMA device is different from the DRM device’s parent. Aftercalling this function, the DRM device holds a reference ondma_dev. Pass NULL to clear the DMA device.

intdrm_dev_wedged_event(structdrm_device*dev,unsignedlongmethod,structdrm_wedge_task_info*info)

generate a device wedged uevent

Parameters

structdrm_device*dev

DRM device

unsignedlongmethod

method(s) to be used for recovery

structdrm_wedge_task_info*info

optional information about the guilty task

Description

This generates a device wedged uevent for the DRM device specified bydev.Recoverymethod(s) of choice will be sent in the uevent environment asWEDGED=<method1>[,..,<methodN>] in order of less to more side-effects.If caller is unsure about recovery ormethod is unknown (0),WEDGED=unknown will be sent instead.

Refer to “Device Wedging” chapter inUserland interfaces for moredetails.

Return

0 on success, negative error code otherwise.

void*__drm_dev_alloc(structdevice*parent,conststructdrm_driver*driver,size_tsize,size_toffset)

Allocation of adrm_device instance

Parameters

structdevice*parent

Parent device object

conststructdrm_driver*driver

DRM driver

size_tsize

the size of thestructwhich containsstructdrm_device

size_toffset

the offset of thedrm_device within the container.

Description

This shouldNOT be by any drivers, but is a dedicated interface for thecorresponding Rust abstraction.

This is the same asdevm_drm_dev_alloc(), but without the correspondingresource management through the parent device, but not the same asdrm_dev_alloc(), since the latter is the deprecated version, which does notsupport subclassing.

Return

A pointer to new DRM device, or an ERR_PTR on failure.

structdrm_device*drm_dev_alloc(conststructdrm_driver*driver,structdevice*parent)

Allocate new DRM device

Parameters

conststructdrm_driver*driver

DRM driver to allocate device for

structdevice*parent

Parent device object

Description

This is the deprecated version ofdevm_drm_dev_alloc(), which does not supportsubclassing through embedding the structdrm_device in a driver privatestructure, and which does not support automatic cleanup through devres.

Return

Pointer to new DRM device, or ERR_PTR on failure.

voiddrm_dev_get(structdrm_device*dev)

Take reference of a DRM device

Parameters

structdrm_device*dev

device to take reference of or NULL

Description

This increases the ref-count ofdev by one. Youmust already own areference when calling this. Usedrm_dev_put() to drop this referenceagain.

This function never fails. However, this function does not provideanyguarantee whether the device is alive or running. It only provides areference to the object and the memory associated with it.

voiddrm_dev_put(structdrm_device*dev)

Drop reference of a DRM device

Parameters

structdrm_device*dev

device to drop reference of or NULL

Description

This decreases the ref-count ofdev by one. The device is destroyed if theref-count drops to zero.

structdmem_cgroup_region*drmm_cgroup_register_region(structdrm_device*dev,constchar*region_name,u64size)

Register a region of a DRM device to cgroups

Parameters

structdrm_device*dev

device for region

constchar*region_name

Region name for registering

u64size

Size of region in bytes

Description

This decreases the ref-count ofdev by one. The device is destroyed if theref-count drops to zero.

intdrm_dev_register(structdrm_device*dev,unsignedlongflags)

Register DRM device

Parameters

structdrm_device*dev

Device to register

unsignedlongflags

Flags passed to the driver’s .load() function

Description

Register the DRM devicedev with the system, advertise device to user-spaceand start normal device operation.dev must be initialized viadrm_dev_init()previously.

Never call this twice on any device!

NOTE

To ensure backward compatibility with existing drivers method thisfunction calls thedrm_driver.load method after registering the devicenodes, creating race conditions. Usage of thedrm_driver.load methods istherefore deprecated, drivers must perform all initialization before callingdrm_dev_register().

Return

0 on success, negative error code on failure.

voiddrm_dev_unregister(structdrm_device*dev)

Unregister DRM device

Parameters

structdrm_device*dev

Device to unregister

Description

Unregister the DRM device from the system. This does the reverse ofdrm_dev_register() but does not deallocate the device. The caller must calldrm_dev_put() to drop their final reference, unless it is managed with devres(as devices allocated withdevm_drm_dev_alloc() are), in which case there isalready an unwind action registered.

A special form of unregistering for hotpluggable devices isdrm_dev_unplug(),which can be called while there are still open users ofdev.

This should be called first in the device teardown code to make sureuserspace can’t access the device instance any more.

Driver Load

Component Helper Usage

DRM drivers that drive hardware where a logical device consists of a pile ofindependent hardware blocks are recommended to use thecomponent helperlibrary. For consistency and better options for code reuse thefollowing guidelines apply:

Memory Manager Initialization

Every DRM driver requires a memory manager which must be initialized atload time. DRM currently contains two memory managers, the TranslationTable Manager (TTM) and the Graphics Execution Manager (GEM). Thisdocument describes the use of the GEM memory manager only. See ? fordetails.

Miscellaneous Device Configuration

Another task that may be necessary for PCI devices during configurationis mapping the video BIOS. On many devices, the VBIOS describes deviceconfiguration, LCD panel timings (if any), and contains flags indicatingdevice state. Mapping the BIOS can be done using thepci_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 hasbeen mapped and any necessary information has been extracted, it shouldbe unmapped; on many devices, the ROM address decoder is shared withother BARs, so leaving it mapped could cause undesired behaviour likehangs or memory corruption.

Managed Resources

Inspired by structdevice managed resources, but tied to the lifetime ofstructdrm_device, which can outlive the underlying physical device, usuallywhen userspace has some open files and other handles to resources still open.

Release actions can be added withdrmm_add_action(), memory allocations canbe done directly withdrmm_kmalloc() and the related functions. Everythingwill be released on the finaldrm_dev_put() in reverse order of how therelease actions have been added and memory has been allocated since driverloading started withdevm_drm_dev_alloc().

Note that release actions and managed memory can also be added and removedduring the lifetime of the driver, all the functions are fully concurrentsafe. But it is recommended to use managed resources only for resources thatchange rarely, if ever, during the lifetime of thedrm_device instance.

voiddrmm_release_action(structdrm_device*dev,drmres_release_taction,void*data)

release a managed action from adrm_device

Parameters

structdrm_device*dev

DRM device

drmres_release_taction

function which would be called whendev is released

void*data

opaque pointer, passed toaction

Description

This function calls theaction previously added bydrmm_add_action()immediately.Theaction is removed from the list of cleanup actions fordev,which means that it won’t be called in the finaldrm_dev_put().

void*drmm_kmalloc(structdrm_device*dev,size_tsize,gfp_tgfp)

drm_device managedkmalloc()

Parameters

structdrm_device*dev

DRM device

size_tsize

size of the memory allocation

gfp_tgfp

GFP allocation flags

Description

This is adrm_device managed version ofkmalloc(). The allocated memory isautomatically freed on the finaldrm_dev_put(). Memory can also be freedbefore the finaldrm_dev_put() by callingdrmm_kfree().

char*drmm_kstrdup(structdrm_device*dev,constchar*s,gfp_tgfp)

drm_device managedkstrdup()

Parameters

structdrm_device*dev

DRM device

constchar*s

0-terminated string to be duplicated

gfp_tgfp

GFP allocation flags

Description

This is adrm_device managed version ofkstrdup(). The allocated memory isautomatically freed on the finaldrm_dev_put() and works exactly like amemory allocation obtained bydrmm_kmalloc().

voiddrmm_kfree(structdrm_device*dev,void*data)

drm_device managedkfree()

Parameters

structdrm_device*dev

DRM device

void*data

memory allocation to be freed

Description

This is adrm_device managed version ofkfree() which can be used torelease memory allocated throughdrmm_kmalloc() or any of its relatedfunctions before the finaldrm_dev_put() ofdev.

drmm_add_action

drmm_add_action(dev,action,data)

add a managed release action to adrm_device

Parameters

dev

DRM device

action

function which should be called whendev is released

data

opaque pointer, passed toaction

Description

This function adds therelease action with optional parameterdata to thelist of cleanup actions fordev. The cleanup actions will be run in reverseorder in the finaldrm_dev_put() call fordev.

drmm_add_action_or_reset

drmm_add_action_or_reset(dev,action,data)

add a managed release action to adrm_device

Parameters

dev

DRM device

action

function which should be called whendev is released

data

opaque pointer, passed toaction

Description

Similar todrmm_add_action(), with the only difference that upon failureaction is directly called for any cleanup work necessary on failures.

void*drmm_kzalloc(structdrm_device*dev,size_tsize,gfp_tgfp)

drm_device managedkzalloc()

Parameters

structdrm_device*dev

DRM device

size_tsize

size of the memory allocation

gfp_tgfp

GFP allocation flags

Description

This is adrm_device managed version ofkzalloc(). The allocated memory isautomatically freed on the finaldrm_dev_put(). Memory can also be freedbefore the finaldrm_dev_put() by callingdrmm_kfree().

void*drmm_kmalloc_array(structdrm_device*dev,size_tn,size_tsize,gfp_tflags)

drm_device managedkmalloc_array()

Parameters

structdrm_device*dev

DRM device

size_tn

number of array elements to allocate

size_tsize

size of array member

gfp_tflags

GFP allocation flags

Description

This is adrm_device managed version ofkmalloc_array(). The allocatedmemory is automatically freed on the finaldrm_dev_put() and works exactlylike a memory allocation obtained bydrmm_kmalloc().

void*drmm_kcalloc(structdrm_device*dev,size_tn,size_tsize,gfp_tflags)

drm_device managedkcalloc()

Parameters

structdrm_device*dev

DRM device

size_tn

number of array elements to allocate

size_tsize

size of array member

gfp_tflags

GFP allocation flags

Description

This is adrm_device managed version ofkcalloc(). The allocated memory isautomatically freed on the finaldrm_dev_put() and works exactly like amemory allocation obtained bydrmm_kmalloc().

drmm_mutex_init

drmm_mutex_init(dev,lock)

Parameters

dev

DRM device

lock

lock to be initialized

Return

0 on success, or a negative errno code otherwise.

Description

This is adrm_device-managed version ofmutex_init(). The initializedlock is automatically destroyed on the finaldrm_dev_put().

drmm_alloc_ordered_workqueue

drmm_alloc_ordered_workqueue(dev,fmt,flags,args...)

Parameters

dev

DRM device

fmt

printf format for the name of the workqueue

flags

WQ_* flags (only WQ_FREEZABLE and WQ_MEM_RECLAIM are meaningful)

args...

args forfmt

Description

This is adrm_device-managed version ofalloc_ordered_workqueue(). Theallocated workqueue is automatically destroyed on the finaldrm_dev_put().

Return

workqueue on success, negative ERR_PTR otherwise.

Open/Close, File Operations and IOCTLs

File Operations

Drivers must define the file operations structure that forms the DRMuserspace API entry point, even though most of those operations areimplemented in the DRM core. The resultingstructfile_operations must bestored in thedrm_driver.fops field. The mandatory functions aredrm_open(),drm_read(),drm_ioctl() anddrm_compat_ioctl() if CONFIG_COMPAT is enabledNote that drm_compat_ioctl will be NULL if CONFIG_COMPAT=n, so there’s noneed to sprinkle #ifdef into the code. Drivers which implement private ioctlsthat require 32/64 bit compatibility support must provide their ownfile_operations.compat_ioctl handler that processes private ioctls and callsdrm_compat_ioctl() for core ioctls.

In additiondrm_read() anddrm_poll() provide support for DRM events. DRMevents are a generic and extensible means to send asynchronous events touserspace through the file descriptor. They are used to send vblank event andpage flip completions by the KMS API. But drivers can also use it for theirown needs, e.g. to signal completion of rendering.

For the driver-side event interface seedrm_event_reserve_init() anddrm_send_event() as the main starting points.

The memory mapping implementation will vary depending on how the drivermanages memory. For GEM-based drivers this isdrm_gem_mmap().

No other file operations are supported by the DRM userspace API. Overall thefollowing is an examplefile_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,        .mmap = drm_gem_mmap,};

For plain GEM based drivers there is theDEFINE_DRM_GEM_FOPS() macro, and forDMA based drivers there is theDEFINE_DRM_GEM_DMA_FOPS() macro to make thissimpler.

The driver’sfile_operations must be stored indrm_driver.fops.

For driver-private IOCTL handling see the more detailed discussion inIOCTL support in the userland interfaces chapter.

structdrm_minor

DRM device minor structure

Definition:

struct drm_minor {};

Members

Description

This structure represents a DRM minor number for device nodes in /dev.Entirely opaque to drivers and should never be inspected directly by drivers.Drivers instead should only interact withstructdrm_file and of coursestructdrm_device, which is also where driver-private data and resources canbe attached to.

structdrm_pending_event

Event queued up for userspace to read

Definition:

struct drm_pending_event {    struct completion *completion;    void (*completion_release)(struct completion *completion);    struct drm_event *event;    struct dma_fence *fence;    struct drm_file *file_priv;    struct list_head link;    struct list_head pending_link;};

Members

completion

Optional pointer to a kernel internal completion signalled whendrm_send_event() is called, useful to internally synchronize withnonblocking operations.

completion_release

Optional callback currently only used by the atomic modeset helpersto clean up the reference count for the structurecompletion isstored in.

event

Pointer to the actual event that should be sent to userspace to beread usingdrm_read(). Can be optional, since nowadays events arealso used to signal kernel internal threads withcompletion or DMAtransactions usingfence.

fence

Optional DMA fence to unblock other hardware transactions whichdepend upon the nonblocking DRM operation this event represents.

file_priv

structdrm_file whereevent should be delivered to. Only set whenevent is set.

link

Double-linked list to keep track of this event. Can be used by thedriver up to the point when it callsdrm_send_event(), after thatthis list entry is owned by the core for its own book-keeping.

pending_link

Entry ondrm_file.pending_event_list, to keep track of all pendingevents forfile_priv, to allow correct unwinding of them whenuserspace closes the file before the event is delivered.

Description

This represents a DRM event. Drivers can use this as a generic completionmechanism, which supports kernel-internalstructcompletion,structdma_fenceand also the DRM-specificstructdrm_event delivery mechanism.

structdrm_file

DRM file private data

Definition:

struct drm_file {    bool authenticated;    bool stereo_allowed;    bool universal_planes;    bool atomic;    bool aspect_ratio_allowed;    bool writeback_connectors;    bool plane_color_pipeline;    bool was_master;    bool is_master;    bool supports_virtualized_cursor_plane;    struct drm_master *master;    spinlock_t master_lookup_lock;    struct pid  *pid;    u64 client_id;    drm_magic_t magic;    struct list_head lhead;    struct drm_minor *minor;    struct idr object_idr;    spinlock_t table_lock;    struct xarray syncobj_xa;    struct file *filp;    void *driver_priv;    struct list_head fbs;    struct mutex fbs_lock;    struct list_head blobs;    wait_queue_head_t event_wait;    struct list_head pending_event_list;    struct list_head event_list;    int event_space;    struct mutex event_read_lock;    struct drm_prime_file_private prime;    const char *client_name;    struct mutex client_name_lock;    struct dentry *debugfs_client;};

Members

authenticated

Whether the client is allowed to submit rendering, which for legacynodes means it must be authenticated.

See also thesection on primary nodes and authentication.

stereo_allowed

True when the client has asked us to expose stereo 3D mode flags.

universal_planes

True if client understands CRTC primary planes and cursor planesin the plane list. Automatically set whenatomic is set.

atomic

True if client understands atomic properties.

aspect_ratio_allowed

True, if client can handle picture aspect ratios, and has requestedto pass this information along with the mode.

writeback_connectors

True if client understands writeback connectors

plane_color_pipeline

True if client understands plane color pipelines

was_master

This client has or had, master capability. Protected by structdrm_device.master_mutex.

This is used to ensure that CAP_SYS_ADMIN is not enforced, if theclient is or was master in the past.

is_master

This client is the creator ofmaster. Protected by structdrm_device.master_mutex.

See also thesection on primary nodes and authentication.

supports_virtualized_cursor_plane

This client is capable of handling the cursor plane with therestrictions imposed on it by the virtualized drivers.

This implies that the cursor plane has to behave like a cursori.e. track cursor movement. It also requires setting of thehotspot properties by the client on the cursor plane.

master

Master this node is currently associated with. Protected by structdrm_device.master_mutex, and serialized bymaster_lookup_lock.

Only relevant ifdrm_is_primary_client() returns true. Note thatthis only matchesdrm_device.master if the master is the currentlyactive one.

To updatemaster, bothdrm_device.master_mutex andmaster_lookup_lock need to be held, therefore holding either ofthem is safe and enough for the read side.

When dereferencing this pointer, either hold structdrm_device.master_mutex for the duration of the pointer’s use, orusedrm_file_get_master() if structdrm_device.master_mutex is notcurrently held and there is no other need to hold it. This preventsmaster from being freed during use.

See alsoauthentication andis_master and thesection onprimary nodes and authentication.

master_lookup_lock

Serializesmaster.

pid

Process that is using this file.

Must only be dereferenced under a rcu_read_lock or equivalent.

Updates are guarded with dev->filelist_mutex and reference must bedropped after a RCU grace period to accommodate lockless readers.

client_id

A unique id for fdinfo

magic

Authentication magic, seeauthenticated.

lhead

List of all open files of a DRM device, linked intodrm_device.filelist. Protected bydrm_device.filelist_mutex.

minor

structdrm_minor for this file.

object_idr

Mapping of mm object handles to object pointers. Used by the GEMsubsystem. Protected bytable_lock.

Note that allocated entries might be NULL as a transient state whencreating or deleting a handle.

table_lock

Protectsobject_idr.

syncobj_xa

Mapping of sync object handles to object pointers.

filp

Pointer to the core file structure.

driver_priv

Optional pointer for driver private data. Can be allocated indrm_driver.open and should be freed indrm_driver.postclose.

fbs

List ofstructdrm_framebuffer associated with this file, using thedrm_framebuffer.filp_head entry.

Protected byfbs_lock. Note that thefbs list holds a reference onthe framebuffer object to prevent it from untimely disappearing.

fbs_lock

Protectsfbs.

blobs

User-created blob properties; this retains a reference on theproperty.

Protected bydrm_mode_config.blob_lock;

event_wait

Waitqueue for new events added toevent_list.

pending_event_list

List of pendingstructdrm_pending_event, used to clean up pendingevents in case this file gets closed before the event is signalled.Uses thedrm_pending_event.pending_link entry.

Protect bydrm_device.event_lock.

event_list

List ofstructdrm_pending_event, ready for delivery to userspacethroughdrm_read(). Uses thedrm_pending_event.link entry.

Protect bydrm_device.event_lock.

event_space

Available event space to prevent userspace fromexhausting kernel memory. Currently limited to the fairly arbitraryvalue of 4KB.

event_read_lock

Serializesdrm_read().

prime

Per-file buffer caches used by the PRIME buffer sharing code.

client_name

Userspace-provided name; useful for accounting and debugging.

client_name_lock

Protectsclient_name.

debugfs_client

debugfs directory for each client under a drm node.

Description

This structure tracks DRM state per open file descriptor.

booldrm_is_primary_client(conststructdrm_file*file_priv)

is this an open file of the primary node

Parameters

conststructdrm_file*file_priv

DRM file

Description

Returns true if this is an open file of the primary node, i.e.drm_file.minor offile_priv is a primary minor.

See also thesection on primary nodes and authentication.

booldrm_is_render_client(conststructdrm_file*file_priv)

is this an open file of the render node

Parameters

conststructdrm_file*file_priv

DRM file

Description

Returns true if this is an open file of the render node, i.e.drm_file.minor offile_priv is a render minor.

See also thesection on render nodes.

booldrm_is_accel_client(conststructdrm_file*file_priv)

is this an open file of the compute acceleration node

Parameters

conststructdrm_file*file_priv

DRM file

Description

Returns true if this is an open file of the compute acceleration node, i.e.drm_file.minor offile_priv is a accel minor.

See alsoIntroduction to compute accelerators subsystem.

structdrm_memory_stats

GEM object stats associated

Definition:

struct drm_memory_stats {    u64 shared;    u64 private;    u64 resident;    u64 purgeable;    u64 active;};

Members

shared

Total size of GEM objects shared between processes

private

Total size of GEM objects

resident

Total size of GEM objects backing pages

purgeable

Total size of GEM objects that can be purged (resident and not active)

active

Total size of GEM objects active on one or more engines

Description

Used bydrm_print_memory_stats()

intdrm_open(structinode*inode,structfile*filp)

open method for DRM file

Parameters

structinode*inode

device inode

structfile*filp

file pointer.

Description

This function must be used by drivers as theirfile_operations.open method.It looks up the correct DRM device and instantiates all the per-fileresources for it. It also calls thedrm_driver.open driver callback.

Return

0 on success or negative errno value on failure.

intdrm_release(structinode*inode,structfile*filp)

release method for DRM file

Parameters

structinode*inode

device inode

structfile*filp

file pointer.

Description

This function must be used by drivers as theirfile_operations.releasemethod. It frees any resources associated with the open file. If thisis the last open file for the DRM device, it also restores the activein-kernel DRM client.

Return

Always succeeds and returns 0.

intdrm_release_noglobal(structinode*inode,structfile*filp)

release method for DRM file

Parameters

structinode*inode

device inode

structfile*filp

file pointer.

Description

This function may be used by drivers as theirfile_operations.releasemethod. It frees any resources associated with the open file prior to takingthe drm_global_mutex. If this is the last open file for the DRM device, itthen restores the active in-kernel DRM client.

Return

Always succeeds and returns 0.

ssize_tdrm_read(structfile*filp,char__user*buffer,size_tcount,loff_t*offset)

read method for DRM file

Parameters

structfile*filp

file pointer

char__user*buffer

userspace destination pointer for the read

size_tcount

count in bytes to read

loff_t*offset

offset to read

Description

This function must be used by drivers as theirfile_operations.readmethod if they use DRM events for asynchronous signalling to userspace.Since events are used by the KMS API for vblank and page flip completion thismeans all modern display drivers must use it.

offset is ignored, DRM events are read like a pipe. Polling support isprovided bydrm_poll().

This function will only ever read a full event. Therefore userspace mustsupply a big enough buffer to fit any event to ensure forward progress. Sincethe maximum event space is currently 4K it’s recommended to just use that forsafety.

Return

Number of bytes read (always aligned to full events, and can be 0) or anegative error code on failure.

__poll_tdrm_poll(structfile*filp,structpoll_table_struct*wait)

poll method for DRM file

Parameters

structfile*filp

file pointer

structpoll_table_struct*wait

poll waiter table

Description

This function must be used by drivers as theirfile_operations.read methodif they use DRM events for asynchronous signalling to userspace. Sinceevents are used by the KMS API for vblank and page flip completion this meansall modern display drivers must use it.

See alsodrm_read().

Return

Mask of POLL flags indicating the current status of the file.

intdrm_event_reserve_init_locked(structdrm_device*dev,structdrm_file*file_priv,structdrm_pending_event*p,structdrm_event*e)

init a DRM event and reserve space for it

Parameters

structdrm_device*dev

DRM device

structdrm_file*file_priv

DRM file private data

structdrm_pending_event*p

tracking structure for the pending event

structdrm_event*e

actual event data to deliver to userspace

Description

This function prepares the passed in event for eventual delivery. If the eventdoesn’t get delivered (because the IOCTL fails later on, before queuing upanything) then the even must be cancelled and freed usingdrm_event_cancel_free(). Successfully initialized events should be sent outusingdrm_send_event() ordrm_send_event_locked() to signal completion of theasynchronous event to userspace.

If callers embeddedp into a larger structure it must be allocated withkmalloc andp must be the first member element.

This is the locked version ofdrm_event_reserve_init() for callers whichalready holddrm_device.event_lock.

Return

0 on success or a negative error code on failure.

intdrm_event_reserve_init(structdrm_device*dev,structdrm_file*file_priv,structdrm_pending_event*p,structdrm_event*e)

init a DRM event and reserve space for it

Parameters

structdrm_device*dev

DRM device

structdrm_file*file_priv

DRM file private data

structdrm_pending_event*p

tracking structure for the pending event

structdrm_event*e

actual event data to deliver to userspace

Description

This function prepares the passed in event for eventual delivery. If the eventdoesn’t get delivered (because the IOCTL fails later on, before queuing upanything) then the even must be cancelled and freed usingdrm_event_cancel_free(). Successfully initialized events should be sent outusingdrm_send_event() ordrm_send_event_locked() to signal completion of theasynchronous event to userspace.

If callers embeddedp into a larger structure it must be allocated withkmalloc andp must be the first member element.

Callers which already holddrm_device.event_lock should usedrm_event_reserve_init_locked() instead.

Return

0 on success or a negative error code on failure.

voiddrm_event_cancel_free(structdrm_device*dev,structdrm_pending_event*p)

free a DRM event and release its space

Parameters

structdrm_device*dev

DRM device

structdrm_pending_event*p

tracking structure for the pending event

Description

This function frees the eventp initialized withdrm_event_reserve_init()and releases any allocated space. It is used to cancel an event when thenonblocking operation could not be submitted and needed to be aborted.

voiddrm_send_event_timestamp_locked(structdrm_device*dev,structdrm_pending_event*e,ktime_ttimestamp)

send DRM event to file descriptor

Parameters

structdrm_device*dev

DRM device

structdrm_pending_event*e

DRM event to deliver

ktime_ttimestamp

timestamp to set for the fence event in kernel’s CLOCK_MONOTONICtime domain

Description

This function sends the evente, initialized withdrm_event_reserve_init(),to its associated userspace DRM file. Callers must already holddrm_device.event_lock.

Note that the core will take care of unlinking and disarming events when thecorresponding DRM file is closed. Drivers need not worry about whether theDRM file for this event still exists and can call this function uponcompletion of the asynchronous work unconditionally.

voiddrm_send_event_locked(structdrm_device*dev,structdrm_pending_event*e)

send DRM event to file descriptor

Parameters

structdrm_device*dev

DRM device

structdrm_pending_event*e

DRM event to deliver

Description

This function sends the evente, initialized withdrm_event_reserve_init(),to its associated userspace DRM file. Callers must already holddrm_device.event_lock, seedrm_send_event() for the unlocked version.

Note that the core will take care of unlinking and disarming events when thecorresponding DRM file is closed. Drivers need not worry about whether theDRM file for this event still exists and can call this function uponcompletion of the asynchronous work unconditionally.

voiddrm_send_event(structdrm_device*dev,structdrm_pending_event*e)

send DRM event to file descriptor

Parameters

structdrm_device*dev

DRM device

structdrm_pending_event*e

DRM event to deliver

Description

This function sends the evente, initialized withdrm_event_reserve_init(),to its associated userspace DRM file. This function acquiresdrm_device.event_lock, seedrm_send_event_locked() for callers which alreadyhold this lock.

Note that the core will take care of unlinking and disarming events when thecorresponding DRM file is closed. Drivers need not worry about whether theDRM file for this event still exists and can call this function uponcompletion of the asynchronous work unconditionally.

voiddrm_print_memory_stats(structdrm_printer*p,conststructdrm_memory_stats*stats,enumdrm_gem_object_statussupported_status,constchar*region)

A helper to print memory stats

Parameters

structdrm_printer*p

The printer to print output to

conststructdrm_memory_stats*stats

The collected memory stats

enumdrm_gem_object_statussupported_status

Bitmask of optional stats which are available

constchar*region

The memory region

voiddrm_show_memory_stats(structdrm_printer*p,structdrm_file*file)

Helper to collect and show standard fdinfo memory stats

Parameters

structdrm_printer*p

the printer to print output to

structdrm_file*file

the DRM file

Description

Helper to iterate over GEM objects with a handle allocated in the specifiedfile.

voiddrm_show_fdinfo(structseq_file*m,structfile*f)

helper for drm file fops

Parameters

structseq_file*m

output stream

structfile*f

the device file instance

Description

Helper to implement fdinfo, for userspace to query usage stats, etc, of aprocess using the GPU. See alsodrm_driver.show_fdinfo.

For text output format description please seeDRM client usage stats

voiddrm_file_err(structdrm_file*file_priv,constchar*fmt,...)

log process name, pid and client_name associated with a drm_file

Parameters

structdrm_file*file_priv

context of interest for process name and pid

constchar*fmt

printf() like format string

...

variable arguments

Description

Helper function for clients which needs to log process details suchas name and pid etc along with user logs.

Misc Utilities

Printer

A simple wrapper fordev_printk(),seq_printf(), etc. Allows samedebug 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_FSvoid debugfs_show(struct seq_file *f){        struct drm_printer p = drm_seq_file_printer(f);        log_some_info(&p);}#endifvoid some_other_function(...){        struct drm_printer p = drm_info_printer(drm->dev);        log_some_info(&p);}
enumdrm_debug_category

The DRM debug categories

Constants

DRM_UT_CORE

Used in the generic drm code: drm_ioctl.c, drm_mm.c,drm_memory.c, ...

DRM_UT_DRIVER

Used in the vendor specific part of the driver: i915,radeon, ... macro.

DRM_UT_KMS

Used in the modesetting code.

DRM_UT_PRIME

Used in the prime code.

DRM_UT_ATOMIC

Used in the atomic code.

DRM_UT_VBL

Used for verbose debug message in the vblank code.

DRM_UT_STATE

Used for verbose atomic state debugging.

DRM_UT_LEASE

Used in the lease code.

DRM_UT_DP

Used in the DP code.

DRM_UT_DRMRES

Used in the drm managed resources code.

Description

Each of the DRM debug logging macros use a specific category, and the loggingis filtered by the drm.debug module parameter. Thisenumspecifies the valuesfor the interface.

Each DRM_DEBUG_<CATEGORY> macro logs to DRM_UT_<CATEGORY> category, exceptDRM_DEBUG() logs to DRM_UT_CORE.

Enabling verbose debug messages is done through the drm.debug parameter, eachcategory being enabled by a bit:

  • drm.debug=0x1 will enable CORE messages

  • drm.debug=0x2 will enable DRIVER messages

  • drm.debug=0x3 will enable CORE and DRIVER messages

  • ...

  • drm.debug=0x1ff will enable all messages

An interesting feature is that it’s possible to enable verbose logging atrun-time by echoing the debug value in its sysfs node:

# echo 0xf > /sys/module/drm/parameters/debug
structdrm_printer

drm output “stream”

Definition:

struct drm_printer {};

Members

Description

Do not usestructmembers directly. Usedrm_printer_seq_file(),drm_printer_info(), etc to initialize. Anddrm_printf() for output.

voiddrm_vprintf(structdrm_printer*p,constchar*fmt,va_list*va)

print to adrm_printer stream

Parameters

structdrm_printer*p

thedrm_printer

constchar*fmt

format string

va_list*va

the va_list

drm_printf_indent

drm_printf_indent(printer,indent,fmt,...)

Print to adrm_printer stream with indentation

Parameters

printer

DRM printer

indent

Tab indentation level (max 5)

fmt

Format string

...

variable arguments

structdrm_print_iterator

localstructused with drm_printer_coredump

Definition:

struct drm_print_iterator {    void *data;    ssize_t start;    ssize_t remain;};

Members

data

Pointer to the devcoredump output buffer, can be NULL if usingdrm_printer_coredump to determine size of devcoredump

start

The offset within the buffer to start writing

remain

The number of bytes to write for this iteration

structdrm_printerdrm_coredump_printer(structdrm_print_iterator*iter)

construct adrm_printer that can output to a buffer from the read function for devcoredump

Parameters

structdrm_print_iterator*iter

A pointer to astructdrm_print_iterator for the read instance

Description

This wrapper extendsdrm_printf() to work with adev_coredumpm() callbackfunction. The passed in drm_print_iteratorstructcontains the bufferpointer, size and offset as passed in from devcoredump.

For example:

void coredump_read(char *buffer, loff_t offset, size_t count,        void *data, size_t datalen){        struct drm_print_iterator iter;        struct drm_printer p;        iter.data = buffer;        iter.start = offset;        iter.remain = count;        p = drm_coredump_printer(&iter);        drm_printf(p, "foo=%d\n", foo);}void makecoredump(...){        ...        dev_coredumpm(dev, THIS_MODULE, data, 0, GFP_KERNEL,                coredump_read, ...)}

The above example has a time complexity of O(N^2), where N is the size of thedevcoredump. This is acceptable for small devcoredumps but scales poorly forlarger ones.

Another use case for drm_coredump_printer is to capture the devcoredump intoa saved buffer before thedev_coredump() callback. This involves two passes:one to determine the size of the devcoredump and another to print it to abuffer. Then, indev_coredump(), copy from the saved buffer into thedevcoredump read buffer.

For example:

char *devcoredump_saved_buffer;ssize_t __coredump_print(char *buffer, ssize_t count, ...){        struct drm_print_iterator iter;        struct drm_printer p;        iter.data = buffer;        iter.start = 0;        iter.remain = count;        p = drm_coredump_printer(&iter);        drm_printf(p, "foo=%d\n", foo);        ...        return count - iter.remain;}void coredump_print(...){        ssize_t count;        count = __coredump_print(NULL, INT_MAX, ...);        devcoredump_saved_buffer = kvmalloc(count, GFP_KERNEL);        __coredump_print(devcoredump_saved_buffer, count, ...);}void coredump_read(char *buffer, loff_t offset, size_t count,                   void *data, size_t datalen){        ...        memcpy(buffer, devcoredump_saved_buffer + offset, count);        ...}

The above example has a time complexity of O(N*2), where N is the size of thedevcoredump. This scales better than the previous example for largerdevcoredumps.

Return

Thedrm_printer object

booldrm_coredump_printer_is_full(structdrm_printer*p)

DRM coredump printer output is full

Parameters

structdrm_printer*p

DRM coredump printer

Description

DRM printer output is full, useful to short circuit coredump printing onceprinter is full.

Return

True if DRM coredump printer output buffer is full, False otherwise

structdrm_printerdrm_seq_file_printer(structseq_file*f)

construct adrm_printer that outputs toseq_file

Parameters

structseq_file*f

thestructseq_file to output to

Return

Thedrm_printer object

structdrm_printerdrm_info_printer(structdevice*dev)

construct adrm_printer that outputs todev_printk()

Parameters

structdevice*dev

thestructdevice pointer

Return

Thedrm_printer object

structdrm_printerdrm_dbg_printer(structdrm_device*drm,enumdrm_debug_categorycategory,constchar*prefix)

construct adrm_printer for drm device specific output

Parameters

structdrm_device*drm

thestructdrm_device pointer, or NULL

enumdrm_debug_categorycategory

the debug category to use

constchar*prefix

debug output prefix, or NULL for no prefix

Return

Thedrm_printer object

structdrm_printerdrm_err_printer(structdrm_device*drm,constchar*prefix)

construct adrm_printer that outputs todrm_err()

Parameters

structdrm_device*drm

thestructdrm_device pointer

constchar*prefix

debug output prefix, or NULL for no prefix

Return

Thedrm_printer object

structdrm_printerdrm_line_printer(structdrm_printer*p,constchar*prefix,unsignedintseries)

construct adrm_printer that prefixes outputs with line numbers

Parameters

structdrm_printer*p

thestructdrm_printer which actually generates the output

constchar*prefix

optional output prefix, or NULL for no prefix

unsignedintseries

optional unique series identifier, or 0 to omit identifier in the output

Description

This printer can be used to increase the robustness of the captured outputto make sure we didn’t lost any intermediate lines of the output. Helpfulwhile capturing some crash data.

Example 1:

void crash_dump(struct drm_device *drm){        static unsigned int id;        struct drm_printer p = drm_err_printer(drm, "crash");        struct drm_printer lp = drm_line_printer(&p, "dump", ++id);        drm_printf(&lp, "foo");        drm_printf(&lp, "bar");}

Above code will print into the dmesg something like:

[ ] 0000:00:00.0: [drm] *ERROR* crash dump 1.1: foo[ ] 0000:00:00.0: [drm] *ERROR* crash dump 1.2: bar

Example 2:

void line_dump(struct device *dev){        struct drm_printer p = drm_info_printer(dev);        struct drm_printer lp = drm_line_printer(&p, NULL, 0);        drm_printf(&lp, "foo");        drm_printf(&lp, "bar");}

Above code will print:

[ ] 0000:00:00.0: [drm] 1: foo[ ] 0000:00:00.0: [drm] 2: bar

Return

Thedrm_printer object

DRM_DEV_ERROR

DRM_DEV_ERROR(dev,fmt,...)

Error output.

Parameters

dev

device pointer

fmt

printf() like format string.

...

variable arguments

NOTE

this is deprecated in favor ofdrm_err() ordev_err().

DRM_DEV_ERROR_RATELIMITED

DRM_DEV_ERROR_RATELIMITED(dev,fmt,...)

Rate limited error output.

Parameters

dev

device pointer

fmt

printf() like format string.

...

variable arguments

NOTE

this is deprecated in favor ofdrm_err_ratelimited() ordev_err_ratelimited().

Description

LikeDRM_ERROR() but won’t flood the log.

DRM_DEV_DEBUG

DRM_DEV_DEBUG(dev,fmt,...)

Debug output for generic drm code

Parameters

dev

device pointer

fmt

printf() like format string.

...

variable arguments

NOTE

this is deprecated in favor ofdrm_dbg_core().

DRM_DEV_DEBUG_DRIVER

DRM_DEV_DEBUG_DRIVER(dev,fmt,...)

Debug output for vendor specific part of the driver

Parameters

dev

device pointer

fmt

printf() like format string.

...

variable arguments

NOTE

this is deprecated in favor ofdrm_dbg() ordev_dbg().

DRM_DEV_DEBUG_KMS

DRM_DEV_DEBUG_KMS(dev,fmt,...)

Debug output for modesetting code

Parameters

dev

device pointer

fmt

printf() like format string.

...

variable arguments

NOTE

this is deprecated in favor ofdrm_dbg_kms().

voiddrm_puts(structdrm_printer*p,constchar*str)

print a const string to adrm_printer stream

Parameters

structdrm_printer*p

thedrm printer

constchar*str

const string

Description

Allowdrm_printer types that have a constant stringoption to use it.

voiddrm_printf(structdrm_printer*p,constchar*f,...)

print to adrm_printer stream

Parameters

structdrm_printer*p

thedrm_printer

constchar*f

format string

...

variable arguments

voiddrm_print_bits(structdrm_printer*p,unsignedlongvalue,constchar*constbits[],unsignedintnbits)

print bits to adrm_printer stream

Parameters

structdrm_printer*p

thedrm_printer

unsignedlongvalue

field value.

constchar*constbits[]

Array with bit names.

unsignedintnbits

Size of bit names array.

Description

Print bits (in flag fields for example) in human readable form.

voiddrm_print_regset32(structdrm_printer*p,structdebugfs_regset32*regset)

print the contents of registers to adrm_printer stream.

Parameters

structdrm_printer*p

thedrm printer

structdebugfs_regset32*regset

the list of registers to print.

Description

Often in driver debug, it’s useful to be able to either capture thecontents of registers in the steady state using debugfs or atspecific points during operation. This lets the driver have asingle list of registers for both.

voiddrm_print_hex_dump(structdrm_printer*p,constchar*prefix,constu8*buf,size_tlen)

print a hex dump to adrm_printer stream

Parameters

structdrm_printer*p

Thedrm_printer

constchar*prefix

Prefix for each line, may be NULL for no prefix

constu8*buf

Buffer to dump

size_tlen

Length of buffer

Description

Print hex dump todrm_printer, with 16 space-separated hex bytes per line,optionally with a prefix on each line. No separator is added after prefix.

Utilities

Macros and inline functions that does not naturally belong in other places

booldrm_can_sleep(void)

returns true if currently okay to sleep

Parameters

void

no arguments

Description

This function shall not be used in new code.The check for running in atomic context may not work - see linux/preempt.h.

FIXME: All users of drm_can_sleep should be removed (seeTODO list)

Return

False if kgdb is active, we are in atomic context or irqs are disabled.

Unit testing

KUnit

KUnit (Kernel unit testing framework) provides a common framework for unit testswithin the Linux kernel.

This section covers the specifics for the DRM subsystem. For general informationabout KUnit, please refer toGetting Started.

How to run the tests?

In order to facilitate running the test suite, a configuration file is presentindrivers/gpu/drm/tests/.kunitconfig. It can be used bykunit.py asfollows:

$./tools/testing/kunit/kunit.pyrun--kunitconfig=drivers/gpu/drm/tests\--kconfig_addCONFIG_VIRTIO_UML=y\--kconfig_addCONFIG_UML_PCI_OVER_VIRTIO=y

Note

The configuration included in.kunitconfig should be as generic aspossible.CONFIG_VIRTIO_UML andCONFIG_UML_PCI_OVER_VIRTIO are notincluded in it because they are only required for User Mode Linux.

KUnit Coverage Rules

KUnit support is gradually added to the DRM framework and helpers. There’s nogeneral requirement for the framework and helpers to have KUnit tests at themoment. However, patches that are affecting a function or helper alreadycovered by KUnit tests must provide tests if the change calls for one.

Legacy Support Code

The section very briefly covers some of the old legacy support codewhich is only used by old DRM drivers which have done a so-calledshadow-attach to the underlying device instead of registering as a realdriver. This also includes some of the old generic buffer management andcommand submission code. Do not use any of this in new and moderndrivers.

Legacy Suspend/Resume

The DRM core provides some suspend/resume code, but drivers wanting fullsuspend/resume support should providesave() andrestore() functions.These are called at suspend, hibernate, or resume time, and shouldperform any state save or restore required by your device across suspendor hibernate states.

int (*suspend) (structdrm_device *, pm_message_t state); int(*resume) (structdrm_device *);Those are legacy suspend and resume methods whichonly work with thelegacy shadow-attach driver registration functions. New driver shoulduse the power management interface provided by their bus type (usuallythrough thestructdevice_driverdev_pm_ops) and set these methods to NULL.

Legacy DMA Services

This should cover how DMA mapping etc. is supported by the core. Thesefunctions are deprecated and should not be used.