diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2017-05-31 05:22:53 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2017-06-01 02:02:14 -0400 |
commit | 16584b204573ece64de80f20eb6202495aeb35c2 (patch) | |
tree | 655ffd124df38ea5883e146ece397bb270bcffdc | |
parent | 3ed4351a83ca05d3cd886ade6900be1067aa7903 (diff) |
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: Stefan Agner <stefan@agner.ch>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170531092253.12833-1-daniel.vetter@ffwll.ch
-rw-r--r-- | Documentation/gpu/drm-internals.rst | 54 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_irq.c | 30 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_vblank.c | 3 | ||||
-rw-r--r-- | include/drm/drmP.h | 9 | ||||
-rw-r--r-- | include/drm/drm_drv.h | 33 |
5 files changed, 66 insertions, 63 deletions
diff --git a/Documentation/gpu/drm-internals.rst b/Documentation/gpu/drm-internals.rst index 9067cd9586bd..f6882ad0b3c3 100644 --- a/Documentation/gpu/drm-internals.rst +++ b/Documentation/gpu/drm-internals.rst | |||
@@ -149,60 +149,6 @@ Device Instance and Driver Handling | |||
149 | Driver Load | 149 | Driver Load |
150 | ----------- | 150 | ----------- |
151 | 151 | ||
152 | IRQ Registration | ||
153 | ~~~~~~~~~~~~~~~~ | ||
154 | |||
155 | The DRM core tries to facilitate IRQ handler registration and | ||
156 | unregistration by providing :c:func:`drm_irq_install()` and | ||
157 | :c:func:`drm_irq_uninstall()` functions. Those functions only | ||
158 | support a single interrupt per device, devices that use more than one | ||
159 | IRQs need to be handled manually. | ||
160 | |||
161 | Managed IRQ Registration | ||
162 | '''''''''''''''''''''''' | ||
163 | |||
164 | :c:func:`drm_irq_install()` starts by calling the irq_preinstall | ||
165 | driver operation. The operation is optional and must make sure that the | ||
166 | interrupt will not get fired by clearing all pending interrupt flags or | ||
167 | disabling the interrupt. | ||
168 | |||
169 | The passed-in IRQ will then be requested by a call to | ||
170 | :c:func:`request_irq()`. If the DRIVER_IRQ_SHARED driver feature | ||
171 | flag is set, a shared (IRQF_SHARED) IRQ handler will be requested. | ||
172 | |||
173 | The IRQ handler function must be provided as the mandatory irq_handler | ||
174 | driver operation. It will get passed directly to | ||
175 | :c:func:`request_irq()` and thus has the same prototype as all IRQ | ||
176 | handlers. It will get called with a pointer to the DRM device as the | ||
177 | second argument. | ||
178 | |||
179 | Finally the function calls the optional irq_postinstall driver | ||
180 | operation. The operation usually enables interrupts (excluding the | ||
181 | vblank interrupt, which is enabled separately), but drivers may choose | ||
182 | to enable/disable interrupts at a different time. | ||
183 | |||
184 | :c:func:`drm_irq_uninstall()` is similarly used to uninstall an | ||
185 | IRQ handler. It starts by waking up all processes waiting on a vblank | ||
186 | interrupt to make sure they don't hang, and then calls the optional | ||
187 | irq_uninstall driver operation. The operation must disable all hardware | ||
188 | interrupts. Finally the function frees the IRQ by calling | ||
189 | :c:func:`free_irq()`. | ||
190 | |||
191 | Manual IRQ Registration | ||
192 | ''''''''''''''''''''''' | ||
193 | |||
194 | Drivers that require multiple interrupt handlers can't use the managed | ||
195 | IRQ registration functions. In that case IRQs must be registered and | ||
196 | unregistered manually (usually with the :c:func:`request_irq()` and | ||
197 | :c:func:`free_irq()` functions, or their :c:func:`devm_request_irq()` and | ||
198 | :c:func:`devm_free_irq()` equivalents). | ||
199 | |||
200 | When manually registering IRQs, drivers must not set the | ||
201 | DRIVER_HAVE_IRQ driver feature flag, and must not provide the | ||
202 | irq_handler driver operation. They must set the :c:type:`struct | ||
203 | drm_device <drm_device>` irq_enabled field to 1 upon | ||
204 | registration of the IRQs, and clear it to 0 after unregistering the | ||
205 | IRQs. | ||
206 | 152 | ||
207 | IRQ Helper Library | 153 | IRQ Helper Library |
208 | ~~~~~~~~~~~~~~~~~~ | 154 | ~~~~~~~~~~~~~~~~~~ |
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 28d736c3fcb4..3b04c25100ae 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
@@ -62,19 +62,39 @@ | |||
62 | #include "drm_internal.h" | 62 | #include "drm_internal.h" |
63 | 63 | ||
64 | /** | 64 | /** |
65 | * DOC: irq helpers | ||
66 | * | ||
67 | * The DRM core provides very simple support helpers to enable IRQ handling on a | ||
68 | * device through the drm_irq_install() and drm_irq_uninstall() functions. This | ||
69 | * only supports devices with a single interrupt on the main device stored in | ||
70 | * &drm_device.dev and set as the device paramter in drm_dev_alloc(). | ||
71 | * | ||
72 | * These IRQ helpers are strictly optional. Drivers which roll their own only | ||
73 | * need to set &drm_device.irq_enabled to signal the DRM core that vblank | ||
74 | * interrupts are working. Since these helpers don't automatically clean up the | ||
75 | * requested interrupt like e.g. devm_request_irq() they're not really | ||
76 | * recommended. | ||
77 | */ | ||
78 | |||
79 | /** | ||
65 | * drm_irq_install - install IRQ handler | 80 | * drm_irq_install - install IRQ handler |
66 | * @dev: DRM device | 81 | * @dev: DRM device |
67 | * @irq: IRQ number to install the handler for | 82 | * @irq: IRQ number to install the handler for |
68 | * | 83 | * |
69 | * Initializes the IRQ related data. Installs the handler, calling the driver | 84 | * Initializes the IRQ related data. Installs the handler, calling the driver |
70 | * irq_preinstall() and irq_postinstall() functions before and after the | 85 | * &drm_driver.irq_preinstall and &drm_driver.irq_postinstall functions before |
71 | * installation. | 86 | * and after the installation. |
72 | * | 87 | * |
73 | * This is the simplified helper interface provided for drivers with no special | 88 | * This is the simplified helper interface provided for drivers with no special |
74 | * needs. Drivers which need to install interrupt handlers for multiple | 89 | * needs. Drivers which need to install interrupt handlers for multiple |
75 | * interrupts must instead set &drm_device.irq_enabled to signal the DRM core | 90 | * interrupts must instead set &drm_device.irq_enabled to signal the DRM core |
76 | * that vblank interrupts are available. | 91 | * that vblank interrupts are available. |
77 | * | 92 | * |
93 | * @irq must match the interrupt number that would be passed to request_irq(), | ||
94 | * if called directly instead of using this helper function. | ||
95 | * | ||
96 | * &drm_driver.irq_handler is called to handle the registered interrupt. | ||
97 | * | ||
78 | * Returns: | 98 | * Returns: |
79 | * Zero on success or a negative error code on failure. | 99 | * Zero on success or a negative error code on failure. |
80 | */ | 100 | */ |
@@ -136,9 +156,9 @@ EXPORT_SYMBOL(drm_irq_install); | |||
136 | * drm_irq_uninstall - uninstall the IRQ handler | 156 | * drm_irq_uninstall - uninstall the IRQ handler |
137 | * @dev: DRM device | 157 | * @dev: DRM device |
138 | * | 158 | * |
139 | * Calls the driver's irq_uninstall() function and unregisters the IRQ handler. | 159 | * Calls the driver's &drm_driver.irq_uninstall function and unregisters the IRQ |
140 | * This should only be called by drivers which used drm_irq_install() to set up | 160 | * handler. This should only be called by drivers which used drm_irq_install() |
141 | * their interrupt handler. Other drivers must only reset | 161 | * to set up their interrupt handler. Other drivers must only reset |
142 | * &drm_device.irq_enabled to false. | 162 | * &drm_device.irq_enabled to false. |
143 | * | 163 | * |
144 | * Note that for kernel modesetting drivers it is a bug if this function fails. | 164 | * Note that for kernel modesetting drivers it is a bug if this function fails. |
diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 630dc26379b7..463e4d81fb0d 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c | |||
@@ -363,6 +363,9 @@ static void vblank_disable_fn(unsigned long arg) | |||
363 | * @dev: DRM device | 363 | * @dev: DRM device |
364 | * | 364 | * |
365 | * This function cleans up any resources allocated in drm_vblank_init. | 365 | * This function cleans up any resources allocated in drm_vblank_init. |
366 | * | ||
367 | * Drivers which don't use drm_irq_install() need to set &drm_device.irq_enabled | ||
368 | * themselves, to signal to the DRM core that vblank interrupts are enabled. | ||
366 | */ | 369 | */ |
367 | void drm_vblank_cleanup(struct drm_device *dev) | 370 | void drm_vblank_cleanup(struct drm_device *dev) |
368 | { | 371 | { |
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 2e0b76cceb97..39df16af7a4a 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
@@ -377,8 +377,13 @@ struct drm_device { | |||
377 | int last_context; /**< Last current context */ | 377 | int last_context; /**< Last current context */ |
378 | /*@} */ | 378 | /*@} */ |
379 | 379 | ||
380 | /** \name VBLANK IRQ support */ | 380 | /** |
381 | /*@{ */ | 381 | * @irq_enabled: |
382 | * | ||
383 | * Indicates that interrupt handling is enabled, specifically vblank | ||
384 | * handling. Drivers which don't use drm_irq_install() need to set this | ||
385 | * to true manually. | ||
386 | */ | ||
382 | bool irq_enabled; | 387 | bool irq_enabled; |
383 | int irq; | 388 | int irq; |
384 | 389 | ||
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index e64e33b9dd26..18f3181674e8 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h | |||
@@ -327,11 +327,40 @@ struct drm_driver { | |||
327 | struct timeval *vblank_time, | 327 | struct timeval *vblank_time, |
328 | bool in_vblank_irq); | 328 | bool in_vblank_irq); |
329 | 329 | ||
330 | /* these have to be filled in */ | 330 | /** |
331 | 331 | * @irq_handler: | |
332 | * | ||
333 | * Interrupt handler called when using drm_irq_install(). Not used by | ||
334 | * drivers which implement their own interrupt handling. | ||
335 | */ | ||
332 | irqreturn_t(*irq_handler) (int irq, void *arg); | 336 | irqreturn_t(*irq_handler) (int irq, void *arg); |
337 | |||
338 | /** | ||
339 | * @irq_preinstall: | ||
340 | * | ||
341 | * Optional callback used by drm_irq_install() which is called before | ||
342 | * the interrupt handler is registered. This should be used to clear out | ||
343 | * any pending interrupts (from e.g. firmware based drives) and reset | ||
344 | * the interrupt handling registers. | ||
345 | */ | ||
333 | void (*irq_preinstall) (struct drm_device *dev); | 346 | void (*irq_preinstall) (struct drm_device *dev); |
347 | |||
348 | /** | ||
349 | * @irq_postinstall: | ||
350 | * | ||
351 | * Optional callback used by drm_irq_install() which is called after | ||
352 | * the interrupt handler is registered. This should be used to enable | ||
353 | * interrupt generation in the hardware. | ||
354 | */ | ||
334 | int (*irq_postinstall) (struct drm_device *dev); | 355 | int (*irq_postinstall) (struct drm_device *dev); |
356 | |||
357 | /** | ||
358 | * @irq_uninstall: | ||
359 | * | ||
360 | * Optional callback used by drm_irq_uninstall() which is called before | ||
361 | * the interrupt handler is unregistered. This should be used to disable | ||
362 | * interrupt generation in the hardware. | ||
363 | */ | ||
335 | void (*irq_uninstall) (struct drm_device *dev); | 364 | void (*irq_uninstall) (struct drm_device *dev); |
336 | 365 | ||
337 | /** | 366 | /** |