2 * Copyright 2008 Advanced Micro Devices, Inc.
3 * Copyright 2008 Red Hat Inc.
4 * Copyright 2009 Jerome Glisse.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
24 * Authors: Dave Airlie
28 #include <linux/irq.h>
30 #include <drm/drm_crtc_helper.h>
31 #include <drm/amdgpu_drm.h>
33 #include "amdgpu_ih.h"
35 #include "amdgpu_connectors.h"
37 #include <linux/pm_runtime.h>
39 #define AMDGPU_WAIT_IDLE_TIMEOUT 200
42 * Handle hotplug events outside the interrupt handler proper.
45 * amdgpu_hotplug_work_func - display hotplug work handler
49 * This is the hot plug event work handler (all asics).
50 * The work gets scheduled from the irq handler if there
51 * was a hot plug interrupt. It walks the connector table
52 * and calls the hotplug handler for each one, then sends
53 * a drm hotplug event to alert userspace.
55 static void amdgpu_hotplug_work_func(struct work_struct
*work
)
57 struct amdgpu_device
*adev
= container_of(work
, struct amdgpu_device
,
59 struct drm_device
*dev
= adev
->ddev
;
60 struct drm_mode_config
*mode_config
= &dev
->mode_config
;
61 struct drm_connector
*connector
;
63 mutex_lock(&mode_config
->mutex
);
64 if (mode_config
->num_connector
) {
65 list_for_each_entry(connector
, &mode_config
->connector_list
, head
)
66 amdgpu_connector_hotplug(connector
);
68 mutex_unlock(&mode_config
->mutex
);
69 /* Just fire off a uevent and let userspace tell us what to do */
70 drm_helper_hpd_irq_event(dev
);
74 * amdgpu_irq_reset_work_func - execute gpu reset
78 * Execute scheduled gpu reset (cayman+).
79 * This function is called when the irq handler
80 * thinks we need a gpu reset.
82 static void amdgpu_irq_reset_work_func(struct work_struct
*work
)
84 struct amdgpu_device
*adev
= container_of(work
, struct amdgpu_device
,
87 amdgpu_gpu_reset(adev
);
90 /* Disable *all* interrupts */
91 static void amdgpu_irq_disable_all(struct amdgpu_device
*adev
)
93 unsigned long irqflags
;
97 spin_lock_irqsave(&adev
->irq
.lock
, irqflags
);
98 for (i
= 0; i
< AMDGPU_MAX_IRQ_SRC_ID
; ++i
) {
99 struct amdgpu_irq_src
*src
= adev
->irq
.sources
[i
];
101 if (!src
|| !src
->funcs
->set
|| !src
->num_types
)
104 for (j
= 0; j
< src
->num_types
; ++j
) {
105 atomic_set(&src
->enabled_types
[j
], 0);
106 r
= src
->funcs
->set(adev
, src
, j
,
107 AMDGPU_IRQ_STATE_DISABLE
);
109 DRM_ERROR("error disabling interrupt (%d)\n",
113 spin_unlock_irqrestore(&adev
->irq
.lock
, irqflags
);
117 * amdgpu_irq_preinstall - drm irq preinstall callback
119 * @dev: drm dev pointer
121 * Gets the hw ready to enable irqs (all asics).
122 * This function disables all interrupt sources on the GPU.
124 void amdgpu_irq_preinstall(struct drm_device
*dev
)
126 struct amdgpu_device
*adev
= dev
->dev_private
;
128 /* Disable *all* interrupts */
129 amdgpu_irq_disable_all(adev
);
131 amdgpu_ih_process(adev
);
135 * amdgpu_irq_postinstall - drm irq preinstall callback
137 * @dev: drm dev pointer
139 * Handles stuff to be done after enabling irqs (all asics).
140 * Returns 0 on success.
142 int amdgpu_irq_postinstall(struct drm_device
*dev
)
144 dev
->max_vblank_count
= 0x00ffffff;
149 * amdgpu_irq_uninstall - drm irq uninstall callback
151 * @dev: drm dev pointer
153 * This function disables all interrupt sources on the GPU (all asics).
155 void amdgpu_irq_uninstall(struct drm_device
*dev
)
157 struct amdgpu_device
*adev
= dev
->dev_private
;
162 amdgpu_irq_disable_all(adev
);
166 * amdgpu_irq_handler - irq handler
168 * @int irq, void *arg: args
170 * This is the irq handler for the amdgpu driver (all asics).
172 irqreturn_t
amdgpu_irq_handler(int irq
, void *arg
)
174 struct drm_device
*dev
= (struct drm_device
*) arg
;
175 struct amdgpu_device
*adev
= dev
->dev_private
;
178 ret
= amdgpu_ih_process(adev
);
179 if (ret
== IRQ_HANDLED
)
180 pm_runtime_mark_last_busy(dev
->dev
);
185 * amdgpu_msi_ok - asic specific msi checks
187 * @adev: amdgpu device pointer
189 * Handles asic specific MSI checks to determine if
190 * MSIs should be enabled on a particular chip (all asics).
191 * Returns true if MSIs should be enabled, false if MSIs
192 * should not be enabled.
194 static bool amdgpu_msi_ok(struct amdgpu_device
*adev
)
199 else if (amdgpu_msi
== 0)
206 * amdgpu_irq_init - init driver interrupt info
208 * @adev: amdgpu device pointer
210 * Sets up the work irq handlers, vblank init, MSIs, etc. (all asics).
211 * Returns 0 for success, error for failure.
213 int amdgpu_irq_init(struct amdgpu_device
*adev
)
217 spin_lock_init(&adev
->irq
.lock
);
218 r
= drm_vblank_init(adev
->ddev
, adev
->mode_info
.num_crtc
);
222 adev
->ddev
->vblank_disable_allowed
= true;
225 adev
->irq
.msi_enabled
= false;
227 if (amdgpu_msi_ok(adev
)) {
228 int ret
= pci_enable_msi(adev
->pdev
);
230 adev
->irq
.msi_enabled
= true;
231 dev_info(adev
->dev
, "amdgpu: using MSI.\n");
235 INIT_WORK(&adev
->hotplug_work
, amdgpu_hotplug_work_func
);
236 INIT_WORK(&adev
->reset_work
, amdgpu_irq_reset_work_func
);
238 adev
->irq
.installed
= true;
239 r
= drm_irq_install(adev
->ddev
, adev
->ddev
->pdev
->irq
);
241 adev
->irq
.installed
= false;
242 flush_work(&adev
->hotplug_work
);
246 DRM_INFO("amdgpu: irq initialized.\n");
251 * amdgpu_irq_fini - tear down driver interrupt info
253 * @adev: amdgpu device pointer
255 * Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics).
257 void amdgpu_irq_fini(struct amdgpu_device
*adev
)
261 drm_vblank_cleanup(adev
->ddev
);
262 if (adev
->irq
.installed
) {
263 drm_irq_uninstall(adev
->ddev
);
264 adev
->irq
.installed
= false;
265 if (adev
->irq
.msi_enabled
)
266 pci_disable_msi(adev
->pdev
);
267 flush_work(&adev
->hotplug_work
);
270 for (i
= 0; i
< AMDGPU_MAX_IRQ_SRC_ID
; ++i
) {
271 struct amdgpu_irq_src
*src
= adev
->irq
.sources
[i
];
276 kfree(src
->enabled_types
);
277 src
->enabled_types
= NULL
;
281 adev
->irq
.sources
[i
] = NULL
;
287 * amdgpu_irq_add_id - register irq source
289 * @adev: amdgpu device pointer
290 * @src_id: source id for this source
291 * @source: irq source
294 int amdgpu_irq_add_id(struct amdgpu_device
*adev
, unsigned src_id
,
295 struct amdgpu_irq_src
*source
)
297 if (src_id
>= AMDGPU_MAX_IRQ_SRC_ID
)
300 if (adev
->irq
.sources
[src_id
] != NULL
)
306 if (source
->num_types
&& !source
->enabled_types
) {
309 types
= kcalloc(source
->num_types
, sizeof(atomic_t
),
314 source
->enabled_types
= types
;
317 adev
->irq
.sources
[src_id
] = source
;
323 * amdgpu_irq_dispatch - dispatch irq to IP blocks
325 * @adev: amdgpu device pointer
326 * @entry: interrupt vector
328 * Dispatches the irq to the different IP blocks
330 void amdgpu_irq_dispatch(struct amdgpu_device
*adev
,
331 struct amdgpu_iv_entry
*entry
)
333 unsigned src_id
= entry
->src_id
;
334 struct amdgpu_irq_src
*src
;
337 if (src_id
>= AMDGPU_MAX_IRQ_SRC_ID
) {
338 DRM_DEBUG("Invalid src_id in IV: %d\n", src_id
);
342 if (adev
->irq
.virq
[src_id
]) {
343 generic_handle_irq(irq_find_mapping(adev
->irq
.domain
, src_id
));
345 src
= adev
->irq
.sources
[src_id
];
347 DRM_DEBUG("Unhandled interrupt src_id: %d\n", src_id
);
351 r
= src
->funcs
->process(adev
, src
, entry
);
353 DRM_ERROR("error processing interrupt (%d)\n", r
);
358 * amdgpu_irq_update - update hw interrupt state
360 * @adev: amdgpu device pointer
361 * @src: interrupt src you want to enable
362 * @type: type of interrupt you want to update
364 * Updates the interrupt state for a specific src (all asics).
366 int amdgpu_irq_update(struct amdgpu_device
*adev
,
367 struct amdgpu_irq_src
*src
, unsigned type
)
369 unsigned long irqflags
;
370 enum amdgpu_interrupt_state state
;
373 spin_lock_irqsave(&adev
->irq
.lock
, irqflags
);
375 /* we need to determine after taking the lock, otherwise
376 we might disable just enabled interrupts again */
377 if (amdgpu_irq_enabled(adev
, src
, type
))
378 state
= AMDGPU_IRQ_STATE_ENABLE
;
380 state
= AMDGPU_IRQ_STATE_DISABLE
;
382 r
= src
->funcs
->set(adev
, src
, type
, state
);
383 spin_unlock_irqrestore(&adev
->irq
.lock
, irqflags
);
388 * amdgpu_irq_get - enable interrupt
390 * @adev: amdgpu device pointer
391 * @src: interrupt src you want to enable
392 * @type: type of interrupt you want to enable
394 * Enables the interrupt type for a specific src (all asics).
396 int amdgpu_irq_get(struct amdgpu_device
*adev
, struct amdgpu_irq_src
*src
,
399 if (!adev
->ddev
->irq_enabled
)
402 if (type
>= src
->num_types
)
405 if (!src
->enabled_types
|| !src
->funcs
->set
)
408 if (atomic_inc_return(&src
->enabled_types
[type
]) == 1)
409 return amdgpu_irq_update(adev
, src
, type
);
414 bool amdgpu_irq_get_delayed(struct amdgpu_device
*adev
,
415 struct amdgpu_irq_src
*src
,
418 if ((type
>= src
->num_types
) || !src
->enabled_types
)
420 return atomic_inc_return(&src
->enabled_types
[type
]) == 1;
424 * amdgpu_irq_put - disable interrupt
426 * @adev: amdgpu device pointer
427 * @src: interrupt src you want to disable
428 * @type: type of interrupt you want to disable
430 * Disables the interrupt type for a specific src (all asics).
432 int amdgpu_irq_put(struct amdgpu_device
*adev
, struct amdgpu_irq_src
*src
,
435 if (!adev
->ddev
->irq_enabled
)
438 if (type
>= src
->num_types
)
441 if (!src
->enabled_types
|| !src
->funcs
->set
)
444 if (atomic_dec_and_test(&src
->enabled_types
[type
]))
445 return amdgpu_irq_update(adev
, src
, type
);
451 * amdgpu_irq_enabled - test if irq is enabled or not
453 * @adev: amdgpu device pointer
454 * @idx: interrupt src you want to test
456 * Tests if the given interrupt source is enabled or not
458 bool amdgpu_irq_enabled(struct amdgpu_device
*adev
, struct amdgpu_irq_src
*src
,
461 if (!adev
->ddev
->irq_enabled
)
464 if (type
>= src
->num_types
)
467 if (!src
->enabled_types
|| !src
->funcs
->set
)
470 return !!atomic_read(&src
->enabled_types
[type
]);
474 static void amdgpu_irq_mask(struct irq_data
*irqd
)
479 static void amdgpu_irq_unmask(struct irq_data
*irqd
)
484 static struct irq_chip amdgpu_irq_chip
= {
486 .irq_mask
= amdgpu_irq_mask
,
487 .irq_unmask
= amdgpu_irq_unmask
,
490 static int amdgpu_irqdomain_map(struct irq_domain
*d
,
491 unsigned int irq
, irq_hw_number_t hwirq
)
493 if (hwirq
>= AMDGPU_MAX_IRQ_SRC_ID
)
496 irq_set_chip_and_handler(irq
,
497 &amdgpu_irq_chip
, handle_simple_irq
);
501 static struct irq_domain_ops amdgpu_hw_irqdomain_ops
= {
502 .map
= amdgpu_irqdomain_map
,
506 * amdgpu_irq_add_domain - create a linear irq domain
508 * @adev: amdgpu device pointer
510 * Create an irq domain for GPU interrupt sources
511 * that may be driven by another driver (e.g., ACP).
513 int amdgpu_irq_add_domain(struct amdgpu_device
*adev
)
515 adev
->irq
.domain
= irq_domain_add_linear(NULL
, AMDGPU_MAX_IRQ_SRC_ID
,
516 &amdgpu_hw_irqdomain_ops
, adev
);
517 if (!adev
->irq
.domain
) {
518 DRM_ERROR("GPU irq add domain failed\n");
526 * amdgpu_irq_remove_domain - remove the irq domain
528 * @adev: amdgpu device pointer
530 * Remove the irq domain for GPU interrupt sources
531 * that may be driven by another driver (e.g., ACP).
533 void amdgpu_irq_remove_domain(struct amdgpu_device
*adev
)
535 if (adev
->irq
.domain
) {
536 irq_domain_remove(adev
->irq
.domain
);
537 adev
->irq
.domain
= NULL
;
542 * amdgpu_irq_create_mapping - create a mapping between a domain irq and a
545 * @adev: amdgpu device pointer
546 * @src_id: IH source id
548 * Create a mapping between a domain irq (GPU IH src id) and a Linux irq
549 * Use this for components that generate a GPU interrupt, but are driven
550 * by a different driver (e.g., ACP).
551 * Returns the Linux irq.
553 unsigned amdgpu_irq_create_mapping(struct amdgpu_device
*adev
, unsigned src_id
)
555 adev
->irq
.virq
[src_id
] = irq_create_mapping(adev
->irq
.domain
, src_id
);
557 return adev
->irq
.virq
[src_id
];