Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 16584b20 authored by Daniel Vetter's avatar Daniel Vetter
Browse files

drm/doc: Polish irq helper documentation



Pull a (much shorter) overview into drm_irq.c, and instead put the
callback documentation into in-line comments in drm_drv.h.

v2: Move the include stanzas back to the split-up patch (Stefan).

Cc: Stefan Agner <stefan@agner.ch>
Reviewed-by: default avatarStefan Agner <stefan@agner.ch>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170531092253.12833-1-daniel.vetter@ffwll.ch
parent 3ed4351a
Loading
Loading
Loading
Loading
+0 −54
Original line number Diff line number Diff line
@@ -149,60 +149,6 @@ Device Instance and Driver Handling
Driver Load
-----------

IRQ Registration
~~~~~~~~~~~~~~~~

The DRM core tries to facilitate IRQ handler registration and
unregistration by providing :c:func:`drm_irq_install()` and
:c:func:`drm_irq_uninstall()` functions. Those functions only
support a single interrupt per device, devices that use more than one
IRQs need to be handled manually.

Managed IRQ Registration
''''''''''''''''''''''''

:c:func:`drm_irq_install()` starts by calling the irq_preinstall
driver operation. The operation is optional and must make sure that the
interrupt will not get fired by clearing all pending interrupt flags or
disabling the interrupt.

The passed-in IRQ will then be requested by a call to
:c:func:`request_irq()`. If the DRIVER_IRQ_SHARED driver feature
flag is set, a shared (IRQF_SHARED) IRQ handler will be requested.

The IRQ handler function must be provided as the mandatory irq_handler
driver operation. It will get passed directly to
:c:func:`request_irq()` and thus has the same prototype as all IRQ
handlers. It will get called with a pointer to the DRM device as the
second argument.

Finally the function calls the optional irq_postinstall driver
operation. The operation usually enables interrupts (excluding the
vblank interrupt, which is enabled separately), but drivers may choose
to enable/disable interrupts at a different time.

:c:func:`drm_irq_uninstall()` is similarly used to uninstall an
IRQ handler. It starts by waking up all processes waiting on a vblank
interrupt to make sure they don't hang, and then calls the optional
irq_uninstall driver operation. The operation must disable all hardware
interrupts. Finally the function frees the IRQ by calling
:c:func:`free_irq()`.

Manual IRQ Registration
'''''''''''''''''''''''

Drivers that require multiple interrupt handlers can't use the managed
IRQ registration functions. In that case IRQs must be registered and
unregistered manually (usually with the :c:func:`request_irq()` and
:c:func:`free_irq()` functions, or their :c:func:`devm_request_irq()` and
:c:func:`devm_free_irq()` equivalents).

When manually registering IRQs, drivers must not set the
DRIVER_HAVE_IRQ driver feature flag, and must not provide the
irq_handler driver operation. They must set the :c:type:`struct
drm_device <drm_device>` irq_enabled field to 1 upon
registration of the IRQs, and clear it to 0 after unregistering the
IRQs.

IRQ Helper Library
~~~~~~~~~~~~~~~~~~
+25 −5
Original line number Diff line number Diff line
@@ -61,20 +61,40 @@

#include "drm_internal.h"

/**
 * DOC: irq helpers
 *
 * The DRM core provides very simple support helpers to enable IRQ handling on a
 * device through the drm_irq_install() and drm_irq_uninstall() functions. This
 * only supports devices with a single interrupt on the main device stored in
 * &drm_device.dev and set as the device paramter in drm_dev_alloc().
 *
 * These IRQ helpers are strictly optional. Drivers which roll their own only
 * need to set &drm_device.irq_enabled to signal the DRM core that vblank
 * interrupts are working. Since these helpers don't automatically clean up the
 * requested interrupt like e.g. devm_request_irq() they're not really
 * recommended.
 */

/**
 * drm_irq_install - install IRQ handler
 * @dev: DRM device
 * @irq: IRQ number to install the handler for
 *
 * Initializes the IRQ related data. Installs the handler, calling the driver
 * irq_preinstall() and irq_postinstall() functions before and after the
 * installation.
 * &drm_driver.irq_preinstall and &drm_driver.irq_postinstall functions before
 * and after the installation.
 *
 * This is the simplified helper interface provided for drivers with no special
 * needs. Drivers which need to install interrupt handlers for multiple
 * interrupts must instead set &drm_device.irq_enabled to signal the DRM core
 * that vblank interrupts are available.
 *
 * @irq must match the interrupt number that would be passed to request_irq(),
 * if called directly instead of using this helper function.
 *
 * &drm_driver.irq_handler is called to handle the registered interrupt.
 *
 * Returns:
 * Zero on success or a negative error code on failure.
 */
@@ -136,9 +156,9 @@ EXPORT_SYMBOL(drm_irq_install);
 * drm_irq_uninstall - uninstall the IRQ handler
 * @dev: DRM device
 *
 * Calls the driver's irq_uninstall() function and unregisters the IRQ handler.
 * This should only be called by drivers which used drm_irq_install() to set up
 * their interrupt handler. Other drivers must only reset
 * Calls the driver's &drm_driver.irq_uninstall function and unregisters the IRQ
 * handler.  This should only be called by drivers which used drm_irq_install()
 * to set up their interrupt handler. Other drivers must only reset
 * &drm_device.irq_enabled to false.
 *
 * Note that for kernel modesetting drivers it is a bug if this function fails.
+3 −0
Original line number Diff line number Diff line
@@ -363,6 +363,9 @@ static void vblank_disable_fn(unsigned long arg)
 * @dev: DRM device
 *
 * This function cleans up any resources allocated in drm_vblank_init.
 *
 * Drivers which don't use drm_irq_install() need to set &drm_device.irq_enabled
 * themselves, to signal to the DRM core that vblank interrupts are enabled.
 */
void drm_vblank_cleanup(struct drm_device *dev)
{
+7 −2
Original line number Diff line number Diff line
@@ -377,8 +377,13 @@ struct drm_device {
	int last_context;		/**< Last current context */
	/*@} */

	/** \name VBLANK IRQ support */
	/*@{ */
	/**
	 * @irq_enabled:
	 *
	 * Indicates that interrupt handling is enabled, specifically vblank
	 * handling. Drivers which don't use drm_irq_install() need to set this
	 * to true manually.
	 */
	bool irq_enabled;
	int irq;

+31 −2
Original line number Diff line number Diff line
@@ -327,11 +327,40 @@ struct drm_driver {
				     struct timeval *vblank_time,
				     bool in_vblank_irq);

	/* these have to be filled in */

	/**
	 * @irq_handler:
	 *
	 * Interrupt handler called when using drm_irq_install(). Not used by
	 * drivers which implement their own interrupt handling.
	 */
	irqreturn_t(*irq_handler) (int irq, void *arg);

	/**
	 * @irq_preinstall:
	 *
	 * Optional callback used by drm_irq_install() which is called before
	 * the interrupt handler is registered. This should be used to clear out
	 * any pending interrupts (from e.g. firmware based drives) and reset
	 * the interrupt handling registers.
	 */
	void (*irq_preinstall) (struct drm_device *dev);

	/**
	 * @irq_postinstall:
	 *
	 * Optional callback used by drm_irq_install() which is called after
	 * the interrupt handler is registered. This should be used to enable
	 * interrupt generation in the hardware.
	 */
	int (*irq_postinstall) (struct drm_device *dev);

	/**
	 * @irq_uninstall:
	 *
	 * Optional callback used by drm_irq_uninstall() which is called before
	 * the interrupt handler is unregistered. This should be used to disable
	 * interrupt generation in the hardware.
	 */
	void (*irq_uninstall) (struct drm_device *dev);

	/**