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’s set_version() method will becalled 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 throughDRM_IOCTL_VERSION.
The driver description is a purely informative string passed touserspace through the DRM_IOCTL_VERSION ioctl and otherwise unused bythe kernel.
The driver date, formatted as YYYYMMDD, is meant to identify the date ofthe latest modification to the driver. However, as most drivers fail toupdate it, its value is mostly useless. The DRM core prints it to thekernel log at initialization time and passes it to userspace through theDRM_IOCTL_VERSION ioctl.
Device Instance and Driver Handling¶
A device instance for a drm driver is represented bystructdrm_device. Thisis initialized withdrm_dev_init(), usually from bus-specific ->probe()callbacks implemented by the driver. The driver then needs to initialize allthe various subsystems for the drm device like memory management, vblankhandling, modesetting support and intial output configuration plus obviouslyinitialize all the corresponding hardware bits. Finally when everything is upand running and ready for userspace the device instance can be publishedusingdrm_dev_register().
There is also deprecated support for initalizing 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 the probe() function and the other functions that isalmost always present and serves as a demonstration ofdevm_drm_dev_init().
structdriver_device{structdrm_devicedrm;void*userspace_facing;structclk*pclk;};staticstructdrm_driverdriver_drm_driver={[...]};staticintdriver_probe(structplatform_device*pdev){structdriver_device*priv;structdrm_device*drm;intret;// devm_kzalloc() can't be used here because the drm_device '// lifetime can exceed the device lifetime if driver unbind// happens when userspace still has open file descriptors.priv=kzalloc(sizeof(*priv),GFP_KERNEL);if(!priv)return-ENOMEM;drm=&priv->drm;ret=devm_drm_dev_init(&pdev->dev,drm,&driver_drm_driver);if(ret){kfree(priv);returnret;}drmm_add_final_kfree(drm,priv);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_generic_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,possibily leaving the hardware enabled.
- enum
switch_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
- struct
drm_device¶ DRM device structure
Definition
struct drm_device { struct list_head legacy_dev_list; int if_version; struct kref ref; struct device *dev; struct { struct list_head resources; void *final_kfree; spinlock_t lock; } managed; struct drm_driver *driver; void *dev_private; struct drm_minor *primary; struct drm_minor *render; bool registered; struct drm_master *master; u32 driver_features; bool unplugged; struct inode *anon_inode; char *unique; struct mutex struct_mutex; 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; bool irq_enabled; int irq; 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; struct drm_agp_head *agp; struct pci_dev *pdev;#ifdef __alpha__; struct pci_controller *hose;#endif; 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;};Members
legacy_dev_list- List of devices per driver for stealth attach cleanup
if_version- Highest interface version set
ref- Object ref-count
dev- Device structure of bus-device
managed- Managed resources linked to the lifetime of this
drm_deviceastracked byref. driver- DRM driver managing the device
dev_privateDRM driver private data. This is deprecated and should be left set toNULL.
Instead of using this pointer it is recommended that drivers use
drm_dev_init()and embed structdrm_devicein their largerper-device structure.primary- Primary node
render- Render node
registered- Internally used by
drm_dev_register()anddrm_connector_register(). master- Currently active master for this device.Protected by
master_mutex driver_featuresper-device driver features
Drivers can clear specific flags here to disallowcertain features on a per-device basis while stillsharing a single
structdrm_driverinstance acrossall devices.unplugged- Flag to tell if the device has been unplugged.See
drm_dev_enter()anddrm_dev_is_unplugged(). anon_inode- inode for private address-space
unique- Unique name of the device
struct_mutexLock for others (not
drm_minor.masteranddrm_file.is_master)WARNING:Only drivers annotated with DRIVER_LEGACY should be using this.
master_mutex- Lock for
drm_minor.masteranddrm_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 through
drm_file.lhead. filelist_internal- List of open DRM files for in-kernel clients.Protected by
filelist_mutex. clientlist_mutex- Protects
clientlistaccess. clientlist- List of in-kernel clients. Protected by
clientlist_mutex. irq_enabled- Indicates that interrupt handling is enabled, specifically vblankhandling. Drivers which don’t use
drm_irq_install()need to set thisto true manually. irq- Used by the
drm_irq_install()and drm_irq_unistall() helpers. vblank_disable_immediateIf 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 uses
drm_crtc_vblank_on()anddrm_crtc_vblank_off()appropriately. See alsomax_vblank_count anddrm_crtc_funcs.get_vblank_counter.vblank- Array of vblank tracking structures, one per
structdrm_crtc. Forhistorical reasons (vblank support predates kernel modesetting) thisis free-standing and not part ofstructdrm_crtcitself. 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_countMaximum 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 value
drm_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_countermust be set.vblank_event_list- List of vblank events
event_lock- Protectsvblank_event_list and event delivery ingeneral. See
drm_send_event()anddrm_send_event_locked(). agp- AGP data
pdev- PCI device structure
hose- PCI hose, only used on ALPHA platforms.
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 the
vga_switcheroo_client_ops.set_gpu_statecallback fb_helper- Pointer to the fbdev emulation structure.Set by
drm_fb_helper_init()and cleared bydrm_fb_helper_fini().
Description
This structure represent a complete card thatmay contain multiple heads.
- enum
drm_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 the 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 supports
drm_syncobjfor explicit synchronization of commandsubmission. DRIVER_SYNCOBJ_TIMELINE- Driver supports the timeline flavor of
drm_syncobjfor explicitsynchronization of command submission. DRIVER_USE_AGP- Set up DRM AGP support, see drm_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_IRQLegacy irq support. Only for legacy drivers. Do not use.
New drivers can either use the
drm_irq_install()anddrm_irq_uninstall()helper functions, or roll their own irq supportcode by callingrequest_irq()directly.DRIVER_KMS_LEGACY_CONTEXT- Used only by nouveau for backwards compatibility with existinguserspace. Do not use.
Description
Seedrm_driver.driver_features, drm_device.driver_features anddrm_core_check_feature().
- struct
drm_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 (*lastclose) (struct drm_device *); void (*unload) (struct drm_device *); void (*release) (struct drm_device *); irqreturn_t(*irq_handler) (int irq, void *arg); void (*irq_preinstall) (struct drm_device *dev); int (*irq_postinstall) (struct drm_device *dev); void (*irq_uninstall) (struct drm_device *dev); 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); void (*gem_free_object_unlocked) (struct drm_gem_object *obj); int (*gem_open_object) (struct drm_gem_object *, struct drm_file *); void (*gem_close_object) (struct drm_gem_object *, struct drm_file *); 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 dma_buf * (*gem_prime_export)(struct drm_gem_object *obj, int flags); struct drm_gem_object * (*gem_prime_import)(struct drm_device *dev, struct dma_buf *dma_buf); int (*gem_prime_pin)(struct drm_gem_object *obj); void (*gem_prime_unpin)(struct drm_gem_object *obj); struct sg_table *(*gem_prime_get_sg_table)(struct drm_gem_object *obj); struct drm_gem_object *(*gem_prime_import_sg_table)(struct drm_device *dev,struct dma_buf_attachment *attach, struct sg_table *sgt); void *(*gem_prime_vmap)(struct drm_gem_object *obj); void (*gem_prime_vunmap)(struct drm_gem_object *obj, void *vaddr); int (*gem_prime_mmap)(struct drm_gem_object *obj, struct vm_area_struct *vma); 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); const struct vm_operations_struct *gem_vm_ops; int major; int minor; int patchlevel; char *name; char *desc; char *date; u32 driver_features; const struct drm_ioctl_desc *ioctls; int num_ioctls; const struct file_operations *fops;};Members
loadBackward-compatible driver callback to completeinitialization steps after the driver is registered. Forthis reason, may suffer from race conditions and its use isdeprecated for new drivers. It is therefore only supportedfor existing drivers not yet converted to the new scheme.See
drm_dev_init()anddrm_dev_register()for proper andrace-free way to set up astructdrm_device.This is deprecated, do not use!
Returns:
Zero on success, non-zero value on failure.
openDriver callback when a new
structdrm_fileis 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 exactlyone
structdrm_file(seedrm_file.is_masteranddrm_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.
postcloseOne of the driver callbacks when a new
structdrm_fileis 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 exactlyone
structdrm_file(seedrm_file.is_masteranddrm_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.lastcloseCalled when the last
structdrm_filehas been closed and there’scurrently no userspace client for thestructdrm_device.Modern drivers should only use this to force-restore the fbdevframebuffer using
drm_fb_helper_restore_fbdev_mode_unlocked().Anything else would indicate there’s something seriously wrong.Modern drivers can also use this to execute delayed power switchingstate changes, e.g. in conjunction with theVGA Switcherooinfrastructure.This is called afterpostclose hook has been called.
NOTE:
All legacy drivers use this callback to de-initialize the hardware.This is purely because of the shadow-attach model, where the DRMkernel driver does not really own the hardware. Instead ownershipe ishandled with the help of userspace through an inheritedly racy danceto set/unset the VT into raw mode.
Legacy drivers initialize the hardware in thefirstopen callback,which isn’t even called for modern drivers.
unloadReverse 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. See
drm_dev_unregister()anddrm_dev_put()for the proper way to remove astructdrm_device.The unload() hook is called right after unregisteringthe device.
releaseOptional 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 a
drm_deviceusingdrmm_add_action(),drmm_kmalloc()and relatedmanaged resources functions.irq_handler- Interrupt handler called when using
drm_irq_install(). Not used bydrivers which implement their own interrupt handling. irq_preinstall- Optional callback used by
drm_irq_install()which is called beforethe interrupt handler is registered. This should be used to clear outany pending interrupts (from e.g. firmware based drives) and resetthe interrupt handling registers. irq_postinstall- Optional callback used by
drm_irq_install()which is called afterthe interrupt handler is registered. This should be used to enableinterrupt generation in the hardware. irq_uninstall- Optional callback used by
drm_irq_uninstall()which is called beforethe interrupt handler is unregistered. This should be used to disableinterrupt generation in the hardware. 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_free_object_unlockeddeconstructor for drm_gem_objects
This is deprecated and should not be used by new drivers. Use
drm_gem_object_funcs.freeinstead.gem_open_objectThis callback is deprecated in favour of
drm_gem_object_funcs.open.Driver hook called upon gem handle creation
gem_close_objectThis callback is deprecated in favour of
drm_gem_object_funcs.close.Driver hook called upon gem handle release
gem_create_objectconstructor for gem objects
Hook for allocating the GEM object struct, for use by the CMA andSHMEM GEM helpers.
prime_handle_to_fdMain PRIME export function. Should be implemented with
drm_gem_prime_handle_to_fd()for GEM based drivers.For an in-depth discussion seePRIME buffer sharingdocumentation.
prime_fd_to_handleMain PRIME import function. Should be implemented with
drm_gem_prime_fd_to_handle()for GEM based drivers.For an in-depth discussion seePRIME buffer sharingdocumentation.
gem_prime_export- Export hook for GEM drivers. Deprecated in favour of
drm_gem_object_funcs.export. gem_prime_importImport hook for GEM drivers.
This defaults to
drm_gem_prime_import()if not set.gem_prime_pin- Deprecated hook in favour of
drm_gem_object_funcs.pin. gem_prime_unpin- Deprecated hook in favour of
drm_gem_object_funcs.unpin. gem_prime_get_sg_table- Deprecated hook in favour of
drm_gem_object_funcs.get_sg_table. gem_prime_import_sg_table- Optional hook used by the PRIME helper functions
drm_gem_prime_import()respectivelydrm_gem_prime_import_dev(). gem_prime_vmap- Deprecated vmap hook for GEM drivers. Please use
drm_gem_object_funcs.vmapinstead. gem_prime_vunmap- Deprecated vunmap hook for GEM drivers. Please use
drm_gem_object_funcs.vunmapinstead. gem_prime_mmapmmap hook for GEM drivers, used to implement dma-buf mmap in thePRIME helpers.
FIXME: There’s way too much duplication going on here, and also movedto
drm_gem_object_funcs.dumb_createThis 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 the
drm_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_offsetAllocate an offset in the drm device node’s address space to be able tomemory map a dumb buffer.
The default implementation is
drm_gem_create_mmap_offset(). GEM baseddrivers must not overwrite this.Called by the user via ioctl.
Returns:
Zero on success, negative errno on failure.
dumb_destroyThis destroys the userspace handle for the given dumb backing storage buffer.Since buffer objects must be reference counted in the kernel a buffer objectwon’t be immediately freed if a framebuffer modeset object still uses it.
Called by the user via ioctl.
The default implementation is
drm_gem_dumb_destroy(). GEM based driversmust not overwrite this.Returns:
Zero on success, negative errno on failure.
gem_vm_opsDriver private ops for this object
For GEM drivers this is deprecated in favour of
drm_gem_object_funcs.vm_ops.major- driver major number
minor- driver minor number
patchlevel- driver patch level
name- driver name
desc- driver description
date- driver date
driver_features- Driver features, see
enumdrm_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(parent,driver,type,member)¶Resource managed allocation of a
drm_deviceinstance
Parameters
parent- Parent device object
driver- DRM driver
type- the type of the struct which contains struct
drm_device member- the name of the
drm_devicewithintype.
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.
- bool
drm_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.
- bool
drm_core_check_all_features(const structdrm_device * dev, u32 features)¶ 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.
- bool
drm_core_check_feature(const structdrm_device * dev, enumdrm_driver_feature feature)¶ 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.
- bool
drm_drv_uses_atomic_modeset(structdrm_device * dev)¶ check if the driver implements atomic_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.
- void
drm_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, calling drm_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.
- bool
drm_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 matching
drm_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.
- void
drm_dev_exit(int idx)¶ Exit device critical section
Parameters
intidx- index returned from
drm_dev_enter()
Description
This function marks the end of a section that should not be entered afterthe device has been unplugged.
- void
drm_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.
- int
drm_dev_init(structdrm_device * dev, structdrm_driver * driver, structdevice * parent)¶ Initialise new DRM device
Parameters
structdrm_device*dev- DRM device
structdrm_driver*driver- DRM driver
structdevice*parent- Parent device object
Description
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.
Drivers that do not want to allocate their own device structembeddingstructdrm_device can calldrm_dev_alloc() instead. For driversthat do embedstructdrm_device it must be placed first in the overallstructure, and the overall structure must be allocated usingkmalloc(): Thedrm core’s release function unconditionally callskfree() on thedev pointerwhen the final reference is released. To override this behaviour, and soallow embedding of the drm_device inside the driver’s device struct at anarbitrary offset, you must supply adrm_driver.release callback and controlthe finalization explicitly.
Note that drivers must calldrmm_add_final_kfree() after this function hascompleted successfully.
Return
0 on success, or error code on failure.
- int
devm_drm_dev_init(structdevice * parent, structdrm_device * dev, structdrm_driver * driver)¶ Resource managed
drm_dev_init()
Parameters
structdevice*parent- Parent device object
structdrm_device*dev- DRM device
structdrm_driver*driver- DRM driver
Description
Manageddrm_dev_init(). The DRM device initialized with this function isautomatically put on driver detach usingdrm_dev_put().
Note that drivers must calldrmm_add_final_kfree() after this function hascompleted successfully.
Return
0 on success, or error code on failure.
- structdrm_device *
drm_dev_alloc(structdrm_driver * driver, structdevice * parent)¶ Allocate new DRM device
Parameters
structdrm_driver*driver- DRM driver to allocate device for
structdevice*parent- Parent device object
Description
Allocate 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.
Note that for purely virtual devicesparent can be NULL.
Drivers that wish to subclass or embedstructdrm_device into theirown struct should look at usingdrm_dev_init() instead.
Return
Pointer to new DRM device, or ERR_PTR on failure.
- void
drm_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.
- void
drm_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.
- int
drm_dev_register(structdrm_device * dev, unsigned long flags)¶ 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.
- void
drm_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.
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.
- int
drm_dev_set_unique(structdrm_device * dev, const char * name)¶ Set the unique name of a DRM device
Parameters
structdrm_device*dev- device of which to set the unique name
constchar*name- unique name
Description
Sets the unique name of a DRM device using the specified string. This isalready done bydrm_dev_init(), drivers should only override the defaultunique name for backwards compatibility reasons.
Return
0 on success or a negative error code on failure.
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:
- The entire device initialization procedure should be run from the
component_master_ops.master_bindcallback, starting withdrm_dev_init(),then binding all components withcomponent_bind_all()and finishing withdrm_dev_register().- The opaque pointer passed to all components through
component_bind_all()should point atstructdrm_deviceof the device instance, not some driverspecific private structure.- The component helper fills the niche where further standardization ofinterfaces is not practical. When there already is, or will be, astandardized interface like
drm_bridgeordrm_panel, providing its ownfunctions to find such components at driver load time, likedrm_of_find_panel_or_bridge(), then the component helper should not beused.
IRQ Helper Library¶
The DRM core provides very simple support helpers to enable IRQ handling on adevice through thedrm_irq_install() anddrm_irq_uninstall() functions. Thisonly supports devices with a single interrupt on the main device stored indrm_device.dev and set as the device paramter indrm_dev_alloc().
These IRQ helpers are strictly optional. Drivers which roll their own onlyneed to setdrm_device.irq_enabled to signal the DRM core that vblankinterrupts are working. Since these helpers don’t automatically clean up therequested interrupt like e.g. devm_request_irq() they’re not reallyrecommended.
- int
drm_irq_install(structdrm_device * dev, int irq)¶ install IRQ handler
Parameters
structdrm_device*dev- DRM device
intirq- IRQ number to install the handler for
Description
Initializes the IRQ related data. Installs the handler, calling the driverdrm_driver.irq_preinstall anddrm_driver.irq_postinstall functions beforeand after the installation.
This is the simplified helper interface provided for drivers with no specialneeds. Drivers which need to install interrupt handlers for multipleinterrupts must instead setdrm_device.irq_enabled to signal the DRM corethat vblank interrupts are available.
irq must match the interrupt number that would be passed torequest_irq(),if called directly instead of using this helper function.
drm_driver.irq_handler is called to handle the registered interrupt.
Return
Zero on success or a negative error code on failure.
- int
drm_irq_uninstall(structdrm_device * dev)¶ uninstall the IRQ handler
Parameters
structdrm_device*dev- DRM device
Description
Calls the driver’sdrm_driver.irq_uninstall function and unregisters the IRQhandler. This should only be called by drivers which useddrm_irq_install()to set up their interrupt handler. Other drivers must only resetdrm_device.irq_enabled to false.
Note that for kernel modesetting drivers it is a bug if this function fails.The sanity checks are only to catch buggy user modesetting drivers which callthe same function through an ioctl.
Return
Zero on success or a negative error code on failure.
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 withdrm_dev_init().
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.
- void
drmm_add_final_kfree(structdrm_device * dev, void * container)¶ add release action for the final
kfree()
Parameters
structdrm_device*dev- DRM device
void*container- pointer to the kmalloc allocation containingdev
Description
Since the allocation containing the structdrm_device must be allocatedbefore it can be initialized withdrm_dev_init() there’s no way to allocatethat memory withdrmm_kmalloc(). To side-step this chicken-egg problem thepointer for this finalkfree() must be specified by calling this function. Itwill be released in the finaldrm_dev_put() fordev, after all other releaseactions installed throughdrmm_add_action() have been processed.
- void *
drmm_kmalloc(structdrm_device * dev, size_t size, gfp_t gfp)¶ drm_devicemanagedkmalloc()
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, const char * s, gfp_t gfp)¶ drm_devicemanagedkstrdup()
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().
- void
drmm_kfree(structdrm_device * dev, void * data)¶ drm_devicemanagedkfree()
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(dev,action,data)¶add a managed release action to a
drm_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(dev,action,data)¶add a managed release action to a
drm_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_t size, gfp_t gfp)¶ drm_devicemanagedkzalloc()
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_t n, size_t size, gfp_t flags)¶ drm_devicemanagedkmalloc_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_t n, size_t size, gfp_t flags)¶ drm_devicemanagedkcalloc()
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().
Bus-specific Device Registration and PCI Support¶
A number of functions are provided to help with device registration. Thefunctions deal with PCI and platform devices respectively and are onlyprovided for historical reasons. These are all deprecated and shouldn’tbe used in new drivers. Besides that there’s a few helpers for pcidrivers.
- drm_dma_handle_t *
drm_pci_alloc(structdrm_device * dev, size_t size, size_t align)¶ Allocate a PCI consistent memory block, for DMA.
Parameters
structdrm_device*dev- DRM device
size_tsize- size of block to allocate
size_talign- alignment of block
Description
FIXME: This is a needless abstraction of the Linux dma-api and should beremoved.
Return
A handle to the allocated memory block on success or NULL onfailure.
- void
drm_pci_free(structdrm_device * dev, drm_dma_handle_t * dmah)¶ Free a PCI consistent memory block
Parameters
structdrm_device*dev- DRM device
drm_dma_handle_t*dmah- handle to memory block
Description
FIXME: This is a needless abstraction of the Linux dma-api and should beremoved.
- int
drm_legacy_pci_init(structdrm_driver * driver, structpci_driver * pdriver)¶ shadow-attach a legacy DRM PCI driver
Parameters
structdrm_driver*driver- DRM device driver
structpci_driver*pdriver- PCI device driver
Description
This is only used by legacy dri1 drivers and deprecated.
Return
0 on success or a negative error code on failure.
- void
drm_legacy_pci_exit(structdrm_driver * driver, structpci_driver * pdriver)¶ unregister shadow-attach legacy DRM driver
Parameters
structdrm_driver*driver- DRM device driver
structpci_driver*pdriver- PCI device driver
Description
Unregister a DRM driver shadow-attached throughdrm_legacy_pci_init(). Thisis deprecated and only used by dri1 drivers.
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. Legacy drivers will use the deprecated drm_legacy_mmap()function, modern drivers should use one of the provided memory-managerspecific implementations. For GEM-based drivers this isdrm_gem_mmap(), andfor drivers which use the CMA GEM helpers it’sdrm_gem_cma_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, .llseek = no_llseek, .mmap = drm_gem_mmap,};For plain GEM based drivers there is theDEFINE_DRM_GEM_FOPS() macro, and forCMA based drivers there is theDEFINE_DRM_GEM_CMA_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.
- struct
drm_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.
- struct
drm_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 when
drm_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 using
drm_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_privstructdrm_filewhereevent 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 calls
drm_send_event(), after thatthis list entry is owned by the core for its own book-keeping. pending_link- Entry on
drm_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.
- struct
drm_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 was_master; bool is_master; struct drm_master *master; struct pid *pid; drm_magic_t magic; struct list_head lhead; struct drm_minor *minor; struct idr object_idr; spinlock_t table_lock; struct idr syncobj_idr; spinlock_t syncobj_table_lock; 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;};Members
authenticatedWhether 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
was_masterThis client has or had, master capability. Protected by struct
drm_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_masterThis client is the creator ofmaster. Protected by struct
drm_device.master_mutex.See also thesection on primary nodes and authentication.
masterMaster this node is currently associated with. Only relevant if
drm_is_primary_client()returns true. Note that this onlymatchesdrm_device.masterif the master is the currently active one.See alsoauthentication andis_master and thesection onprimary nodes and authentication.
pid- Process that opened this file.
magic- Authentication magic, seeauthenticated.
lhead- List of all open files of a DRM device, linked into
drm_device.filelist. Protected bydrm_device.filelist_mutex. minorstructdrm_minorfor this file.object_idr- Mapping of mm object handles to object pointers. Used by the GEMsubsystem. Protected bytable_lock.
table_lock- Protectsobject_idr.
syncobj_idr- Mapping of sync object handles to object pointers.
syncobj_table_lock- Protectssyncobj_idr.
filp- Pointer to the core file structure.
driver_priv- Optional pointer for driver private data. Can be allocated in
drm_driver.openand should be freed indrm_driver.postclose. fbsList of
structdrm_framebufferassociated with this file, using thedrm_framebuffer.filp_headentry.Protected byfbs_lock. Note that thefbs list holds a reference onthe framebuffer object to prevent it from untimely disappearing.
fbs_lock- Protectsfbs.
blobsUser-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_listList of pending
structdrm_pending_event, used to clean up pendingevents in case this file gets closed before the event is signalled.Uses thedrm_pending_event.pending_linkentry.Protect by
drm_device.event_lock.event_listList of
structdrm_pending_event, ready for delivery to userspacethroughdrm_read(). Uses thedrm_pending_event.linkentry.Protect by
drm_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- Serializes
drm_read(). prime- Per-file buffer caches used by the PRIME buffer sharing code.
Description
This structure tracks DRM state per open file descriptor.
- bool
drm_is_primary_client(const structdrm_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.
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.
- int
drm_open(struct inode * inode, struct file * 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.
0 on success or negative errno value on falure.
Return
- int
drm_release(struct inode * inode, struct file * 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, and calls thedrm_driver.postclose driver callback. If this is the last open file for theDRM device also proceeds to call thedrm_driver.lastclose driver callback.
Always succeeds and returns 0.
Return
- int
drm_release_noglobal(struct inode * inode, struct file * 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, which then calls thedrm_driver.postclose drivercallback. If this is the last open file for the DRM device also proceeds tocall thedrm_driver.lastclose driver callback.
Always succeeds and returns 0.
Return
- ssize_t
drm_read(struct file * filp, char __user * buffer, size_t count, 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 iff 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. Therefore drivers alsomust set thefile_operation.llseek to no_llseek(). 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.
Number of bytes read (always aligned to full events, and can be 0) or anegative error code on failure.
Return
- __poll_t
drm_poll(struct file * filp, struct poll_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 methodiff 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().
Mask of POLL flags indicating the current status of the file.
Return
- int
drm_event_reserve_init_locked(structdrm_device * dev, structdrm_file * file_priv, structdrm_pending_event * p, struct drm_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.
0 on success or a negative error code on failure.
Return
- int
drm_event_reserve_init(structdrm_device * dev, structdrm_file * file_priv, structdrm_pending_event * p, struct drm_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.
0 on success or a negative error code on failure.
Return
- void
drm_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.
- void
drm_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.
- void
drm_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.
- unsigned long
drm_get_unmapped_area(struct file * file, unsigned long uaddr, unsigned long len, unsigned long pgoff, unsigned long flags, struct drm_vma_offset_manager * mgr)¶ Get an unused user-space virtual memory area suitable for huge page table entries.
Parameters
structfile*file- The struct file representing the address space being mmap()’d.
unsignedlonguaddr- Start address suggested by user-space.
unsignedlonglen- Length of the area.
unsignedlongpgoff- The page offset into the address space.
unsignedlongflags- mmap flags
structdrm_vma_offset_manager*mgr- The address space manager used by the drm driver. This argument canprobably be removed at some point when all drivers use the sameaddress space manager.
Description
This function attempts to find an unused user-space virtual memory areathat can accommodate the size we want to map, and that is properlyaligned to facilitate huge page table entries matching actualhuge pages or huge page aligned memory in buffer objects. Buffer objectsare assumed to start at huge page boundary pfns (io memory) or bepopulated by huge pages aligned to the start of the buffer object(system- or coherent memory). Adapted from shmem_get_unmapped_area.
Return
aligned user-space address.
Misc Utilities¶
Printer¶
A simple wrapper for dev_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);}- struct
drm_printer¶ drm output “stream”
Definition
struct drm_printer {};Members
Description
Do not use struct members directly. Use drm_printer_seq_file(),drm_printer_info(), etc to initialize. Anddrm_printf() for output.
- void
drm_vprintf(structdrm_printer * p, const char * fmt, va_list * va)¶ print to a
drm_printerstream
Parameters
structdrm_printer*p- the
drm_printer constchar*fmt- format string
va_list*va- the va_list
drm_printf_indent(printer,indent,fmt,…)¶Print to a
drm_printerstream with indentation
Parameters
printer- DRM printer
indent- Tab indentation level (max 5)
fmt- Format string
...- variable arguments
- struct
drm_print_iterator¶ local struct used 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
start- The offset within the buffer to start writing
remain- The number of bytes to write for this iteration
- structdrm_printer
drm_coredump_printer(structdrm_print_iterator * iter)¶ construct a
drm_printerthat can output to a buffer from the read function for devcoredump
Parameters
structdrm_print_iterator*iter- A pointer to a struct drm_print_iterator for the read instance
Description
This wrapper extendsdrm_printf() to work with a dev_coredumpm() callbackfunction. The passed in drm_print_iterator struct contains 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, ...)}Return
Thedrm_printer object
- structdrm_printer
drm_seq_file_printer(struct seq_file * f)¶ construct a
drm_printerthat outputs toseq_file
Parameters
structseq_file*f- the
structseq_fileto output to
Return
Thedrm_printer object
- structdrm_printer
drm_info_printer(structdevice * dev)¶ construct a
drm_printerthat outputs to dev_printk()
Parameters
structdevice*dev- the
structdevicepointer
Return
Thedrm_printer object
- structdrm_printer
drm_debug_printer(const char * prefix)¶ construct a
drm_printerthat outputs topr_debug()
Parameters
constchar*prefix- debug output prefix
Return
Thedrm_printer object
- structdrm_printer
drm_err_printer(const char * prefix)¶ construct a
drm_printerthat outputs topr_err()
Parameters
constchar*prefix- debug output prefix
Return
Thedrm_printer object
- enum
drm_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. This enum specifies 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
DRM_DEV_ERROR(dev,fmt,…)¶
Parameters
dev- device pointer
fmt- printf() like format string.
...- variable arguments
DRM_DEV_ERROR_RATELIMITED(dev,fmt,…)¶
Parameters
dev- device pointer
fmt- printf() like format string.
...- variable arguments
DRM_DEV_DEBUG(dev,fmt,…)¶
Parameters
dev- device pointer
fmt- printf() like format string.
...- variable arguments
- void
drm_puts(structdrm_printer * p, const char * str)¶ print a const string to a
drm_printerstream
Parameters
structdrm_printer*p- the
drmprinter constchar*str- const string
Description
Allowdrm_printer types that have a constant stringoption to use it.
- void
drm_printf(structdrm_printer * p, const char * f, ...)¶ print to a
drm_printerstream
Parameters
structdrm_printer*p- the
drm_printer constchar*f- format string
...- variable arguments
- void
drm_print_bits(structdrm_printer * p, unsigned long value, const char *const bits, unsigned int nbits)¶ print bits to a
drm_printerstream
Parameters
structdrm_printer*p- the
drm_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.
- void
drm_print_regset32(structdrm_printer * p, struct debugfs_regset32 * regset)¶ print the contents of registers to a
drm_printerstream.
Parameters
structdrm_printer*p- the
drmprinter 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.
Utilities¶
Macros and inline functions that does not naturally belong in other places
for_each_if(condition)¶helper for handling conditionals in various for_each macros
Parameters
condition- The condition to check
Description
Typical use:
#define for_each_foo_bar(x, y) \' list_for_each_entry(x, y->list, head) \' for_each_if(x->something == SOMETHING)
Thefor_each_if() macro makes the use of for_each_foo_bar() less errorprone.
- bool
drm_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 (see todo.rst)
Return
False if kgdb is active, we are in atomic context or irqs are disabled.
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 provide save() and restore() 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) (struct drm_device *, pm_message_t state); int(*resume) (struct drm_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.