Open/Close, File Operations and IOCTLs

Open and Close
File Operations
IOCTLs

Open and Close

int (*firstopen) (struct drm_device *);
void (*lastclose) (struct drm_device *);
int (*open) (struct drm_device *, struct drm_file *);
void (*preclose) (struct drm_device *, struct drm_file *);
void (*postclose) (struct drm_device *, struct drm_file *);

Abstract

Open and close handlers. None of those methods are mandatory.

The firstopen method is called by the DRM core for legacy UMS (User Mode Setting) drivers only when an application opens a device that has no other opened file handle. UMS drivers can implement it to acquire device resources. KMS drivers can't use the method and must acquire resources in the load method instead.

Similarly the lastclose method is called when the last application holding a file handle opened on the device closes it, for both UMS and KMS drivers. Additionally, the method is also called at module unload time or, for hot-pluggable devices, when the device is unplugged. The firstopen and lastclose calls can thus be unbalanced.

The open method is called every time the device is opened by an application. Drivers can allocate per-file private data in this method and store them in the struct drm_file driver_priv field. Note that the open method is called before firstopen.

The close operation is split into preclose and postclose methods. Drivers must stop and cleanup all per-file operations in the preclose method. For instance pending vertical blanking and page flip events must be cancelled. No per-file operation is allowed on the file handle after returning from the preclose method.

Finally the postclose method is called as the last step of the close operation, right before calling the lastclose method if no other open file handle exists for the device. Drivers that have allocated per-file private data in the open method should free it here.

The lastclose method should restore CRTC and plane properties to default value, so that a subsequent open of the device will not inherit state from the previous user. It can also be used to execute delayed power switching state changes, e.g. in conjunction with the vga_switcheroo infrastructure (see Part III, “vga_switcheroo”). Beyond that KMS drivers should not do any further cleanup. Only legacy UMS drivers might need to clean up device state so that the vga console or an independent fbdev driver could take over.

File Operations

drm_open — open method for DRM file
drm_release — release method for DRM file
drm_read — read method for DRM file
drm_poll — poll method for DRM file
drm_event_reserve_init_locked — init a DRM event and reserve space for it
drm_event_reserve_init — init a DRM event and reserve space for it
drm_event_cancel_free — free a DRM event and release it's space
drm_send_event_locked — send DRM event to file descriptor
drm_send_event — send DRM event to file descriptor

Drivers must define the file operations structure that forms the DRM userspace API entry point, even though most of those operations are implemented in the DRM core. The mandatory functions are drm_open, drm_read, drm_ioctl and drm_compat_ioctl if CONFIG_COMPAT is enabled. Drivers which implement private ioctls that require 32/64 bit compatibility support must provided their onw .compat_ioctl handler that processes private ioctls and calls drm_compat_ioctl for core ioctls.

In addition drm_read and drm_poll provide support for DRM events. DRM events are a generic and extensible means to send asynchronous events to userspace through the file descriptor. They are used to send vblank event and page flip completions by the KMS API. But drivers can also use it for their own needs, e.g. to signal completion of rendering.

The memory mapping implementation will vary depending on how the driver manages memory. Legacy drivers will use the deprecated drm_legacy_mmap function, modern drivers should use one of the provided memory-manager specific implementations. For GEM-based drivers this is drm_gem_mmap.

No other file operations are supported by the DRM userspace API. Overall the following is an example #file_operations structure:

static const example_drm_fops = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = drm_compat_ioctl, #endif .poll = drm_poll, .read = drm_read, .llseek = no_llseek, .mmap = drm_gem_mmap, };

IOCTLs

drm_noop — DRM no-op ioctl implemntation
drm_invalid_op — DRM invalid ioctl implemntation
drm_ioctl — ioctl callback implementation for DRM drivers
drm_ioctl_flags — Check for core ioctl and return ioctl permission flags
struct drm_ioctl_desc *ioctls;
int num_ioctls;

Abstract

Driver-specific ioctls descriptors table.

Driver-specific ioctls numbers start at DRM_COMMAND_BASE. The ioctls descriptors table is indexed by the ioctl number offset from the base value. Drivers can use the DRM_IOCTL_DEF_DRV() macro to initialize the table entries.

DRM_IOCTL_DEF_DRV(ioctl, func, flags)

ioctl is the ioctl name. Drivers must define the DRM_##ioctl and DRM_IOCTL_##ioctl macros to the ioctl number offset from DRM_COMMAND_BASE and the ioctl number respectively. The first macro is private to the device while the second must be exposed to userspace in a public header.

func is a pointer to the ioctl handler function compatible with the drm_ioctl_t type.

typedef int drm_ioctl_t(struct drm_device *dev, void *data,
		struct drm_file *file_priv);

flags is a bitmask combination of the following values. It restricts how the ioctl is allowed to be called.

  • DRM_AUTH - Only authenticated callers allowed

  • DRM_MASTER - The ioctl can only be called on the master file handle

  • DRM_ROOT_ONLY - Only callers with the SYSADMIN capability allowed

  • DRM_CONTROL_ALLOW - The ioctl can only be called on a control device

  • DRM_UNLOCKED - The ioctl handler will be called without locking the DRM global mutex. This is the enforced default for kms drivers (i.e. using the DRIVER_MODESET flag) and hence shouldn't be used any more for new drivers.