Merge tag 'defconfig-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_irq.c
1 /*
2  * Copyright 2008 Advanced Micro Devices, Inc.
3  * Copyright 2008 Red Hat Inc.
4  * Copyright 2009 Jerome Glisse.
5  *
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:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
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.
23  *
24  * Authors: Dave Airlie
25  *          Alex Deucher
26  *          Jerome Glisse
27  */
28
29 /**
30  * DOC: Interrupt Handling
31  *
32  * Interrupts generated within GPU hardware raise interrupt requests that are
33  * passed to amdgpu IRQ handler which is responsible for detecting source and
34  * type of the interrupt and dispatching matching handlers. If handling an
35  * interrupt requires calling kernel functions that may sleep processing is
36  * dispatched to work handlers.
37  *
38  * If MSI functionality is not disabled by module parameter then MSI
39  * support will be enabled.
40  *
41  * For GPU interrupt sources that may be driven by another driver, IRQ domain
42  * support is used (with mapping between virtual and hardware IRQs).
43  */
44
45 #include <linux/irq.h>
46 #include <linux/pci.h>
47
48 #include <drm/drm_crtc_helper.h>
49 #include <drm/drm_vblank.h>
50 #include <drm/amdgpu_drm.h>
51 #include <drm/drm_drv.h>
52 #include "amdgpu.h"
53 #include "amdgpu_ih.h"
54 #include "atom.h"
55 #include "amdgpu_connectors.h"
56 #include "amdgpu_trace.h"
57 #include "amdgpu_amdkfd.h"
58 #include "amdgpu_ras.h"
59
60 #include <linux/pm_runtime.h>
61
62 #ifdef CONFIG_DRM_AMD_DC
63 #include "amdgpu_dm_irq.h"
64 #endif
65
66 #define AMDGPU_WAIT_IDLE_TIMEOUT 200
67
68 const char *soc15_ih_clientid_name[] = {
69         "IH",
70         "SDMA2 or ACP",
71         "ATHUB",
72         "BIF",
73         "SDMA3 or DCE",
74         "SDMA4 or ISP",
75         "VMC1 or PCIE0",
76         "RLC",
77         "SDMA0",
78         "SDMA1",
79         "SE0SH",
80         "SE1SH",
81         "SE2SH",
82         "SE3SH",
83         "VCN1 or UVD1",
84         "THM",
85         "VCN or UVD",
86         "SDMA5 or VCE0",
87         "VMC",
88         "SDMA6 or XDMA",
89         "GRBM_CP",
90         "ATS",
91         "ROM_SMUIO",
92         "DF",
93         "SDMA7 or VCE1",
94         "PWR",
95         "reserved",
96         "UTCL2",
97         "EA",
98         "UTCL2LOG",
99         "MP0",
100         "MP1"
101 };
102
103 /**
104  * amdgpu_hotplug_work_func - work handler for display hotplug event
105  *
106  * @work: work struct pointer
107  *
108  * This is the hotplug event work handler (all ASICs).
109  * The work gets scheduled from the IRQ handler if there
110  * was a hotplug interrupt.  It walks through the connector table
111  * and calls hotplug handler for each connector. After this, it sends
112  * a DRM hotplug event to alert userspace.
113  *
114  * This design approach is required in order to defer hotplug event handling
115  * from the IRQ handler to a work handler because hotplug handler has to use
116  * mutexes which cannot be locked in an IRQ handler (since &mutex_lock may
117  * sleep).
118  */
119 static void amdgpu_hotplug_work_func(struct work_struct *work)
120 {
121         struct amdgpu_device *adev = container_of(work, struct amdgpu_device,
122                                                   hotplug_work);
123         struct drm_device *dev = adev_to_drm(adev);
124         struct drm_mode_config *mode_config = &dev->mode_config;
125         struct drm_connector *connector;
126         struct drm_connector_list_iter iter;
127
128         mutex_lock(&mode_config->mutex);
129         drm_connector_list_iter_begin(dev, &iter);
130         drm_for_each_connector_iter(connector, &iter)
131                 amdgpu_connector_hotplug(connector);
132         drm_connector_list_iter_end(&iter);
133         mutex_unlock(&mode_config->mutex);
134         /* Just fire off a uevent and let userspace tell us what to do */
135         drm_helper_hpd_irq_event(dev);
136 }
137
138 /**
139  * amdgpu_irq_disable_all - disable *all* interrupts
140  *
141  * @adev: amdgpu device pointer
142  *
143  * Disable all types of interrupts from all sources.
144  */
145 void amdgpu_irq_disable_all(struct amdgpu_device *adev)
146 {
147         unsigned long irqflags;
148         unsigned i, j, k;
149         int r;
150
151         spin_lock_irqsave(&adev->irq.lock, irqflags);
152         for (i = 0; i < AMDGPU_IRQ_CLIENTID_MAX; ++i) {
153                 if (!adev->irq.client[i].sources)
154                         continue;
155
156                 for (j = 0; j < AMDGPU_MAX_IRQ_SRC_ID; ++j) {
157                         struct amdgpu_irq_src *src = adev->irq.client[i].sources[j];
158
159                         if (!src || !src->funcs->set || !src->num_types)
160                                 continue;
161
162                         for (k = 0; k < src->num_types; ++k) {
163                                 atomic_set(&src->enabled_types[k], 0);
164                                 r = src->funcs->set(adev, src, k,
165                                                     AMDGPU_IRQ_STATE_DISABLE);
166                                 if (r)
167                                         DRM_ERROR("error disabling interrupt (%d)\n",
168                                                   r);
169                         }
170                 }
171         }
172         spin_unlock_irqrestore(&adev->irq.lock, irqflags);
173 }
174
175 /**
176  * amdgpu_irq_handler - IRQ handler
177  *
178  * @irq: IRQ number (unused)
179  * @arg: pointer to DRM device
180  *
181  * IRQ handler for amdgpu driver (all ASICs).
182  *
183  * Returns:
184  * result of handling the IRQ, as defined by &irqreturn_t
185  */
186 static irqreturn_t amdgpu_irq_handler(int irq, void *arg)
187 {
188         struct drm_device *dev = (struct drm_device *) arg;
189         struct amdgpu_device *adev = drm_to_adev(dev);
190         irqreturn_t ret;
191
192         ret = amdgpu_ih_process(adev, &adev->irq.ih);
193         if (ret == IRQ_HANDLED)
194                 pm_runtime_mark_last_busy(dev->dev);
195
196         /* For the hardware that cannot enable bif ring for both ras_controller_irq
197          * and ras_err_evnet_athub_irq ih cookies, the driver has to poll status
198          * register to check whether the interrupt is triggered or not, and properly
199          * ack the interrupt if it is there
200          */
201         if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__PCIE_BIF)) {
202                 if (adev->nbio.ras_funcs &&
203                     adev->nbio.ras_funcs->handle_ras_controller_intr_no_bifring)
204                         adev->nbio.ras_funcs->handle_ras_controller_intr_no_bifring(adev);
205
206                 if (adev->nbio.ras_funcs &&
207                     adev->nbio.ras_funcs->handle_ras_err_event_athub_intr_no_bifring)
208                         adev->nbio.ras_funcs->handle_ras_err_event_athub_intr_no_bifring(adev);
209         }
210
211         return ret;
212 }
213
214 /**
215  * amdgpu_irq_handle_ih1 - kick of processing for IH1
216  *
217  * @work: work structure in struct amdgpu_irq
218  *
219  * Kick of processing IH ring 1.
220  */
221 static void amdgpu_irq_handle_ih1(struct work_struct *work)
222 {
223         struct amdgpu_device *adev = container_of(work, struct amdgpu_device,
224                                                   irq.ih1_work);
225
226         amdgpu_ih_process(adev, &adev->irq.ih1);
227 }
228
229 /**
230  * amdgpu_irq_handle_ih2 - kick of processing for IH2
231  *
232  * @work: work structure in struct amdgpu_irq
233  *
234  * Kick of processing IH ring 2.
235  */
236 static void amdgpu_irq_handle_ih2(struct work_struct *work)
237 {
238         struct amdgpu_device *adev = container_of(work, struct amdgpu_device,
239                                                   irq.ih2_work);
240
241         amdgpu_ih_process(adev, &adev->irq.ih2);
242 }
243
244 /**
245  * amdgpu_irq_handle_ih_soft - kick of processing for ih_soft
246  *
247  * @work: work structure in struct amdgpu_irq
248  *
249  * Kick of processing IH soft ring.
250  */
251 static void amdgpu_irq_handle_ih_soft(struct work_struct *work)
252 {
253         struct amdgpu_device *adev = container_of(work, struct amdgpu_device,
254                                                   irq.ih_soft_work);
255
256         amdgpu_ih_process(adev, &adev->irq.ih_soft);
257 }
258
259 /**
260  * amdgpu_msi_ok - check whether MSI functionality is enabled
261  *
262  * @adev: amdgpu device pointer (unused)
263  *
264  * Checks whether MSI functionality has been disabled via module parameter
265  * (all ASICs).
266  *
267  * Returns:
268  * *true* if MSIs are allowed to be enabled or *false* otherwise
269  */
270 static bool amdgpu_msi_ok(struct amdgpu_device *adev)
271 {
272         if (amdgpu_msi == 1)
273                 return true;
274         else if (amdgpu_msi == 0)
275                 return false;
276
277         return true;
278 }
279
280 static void amdgpu_restore_msix(struct amdgpu_device *adev)
281 {
282         u16 ctrl;
283
284         pci_read_config_word(adev->pdev, adev->pdev->msix_cap + PCI_MSIX_FLAGS, &ctrl);
285         if (!(ctrl & PCI_MSIX_FLAGS_ENABLE))
286                 return;
287
288         /* VF FLR */
289         ctrl &= ~PCI_MSIX_FLAGS_ENABLE;
290         pci_write_config_word(adev->pdev, adev->pdev->msix_cap + PCI_MSIX_FLAGS, ctrl);
291         ctrl |= PCI_MSIX_FLAGS_ENABLE;
292         pci_write_config_word(adev->pdev, adev->pdev->msix_cap + PCI_MSIX_FLAGS, ctrl);
293 }
294
295 /**
296  * amdgpu_irq_init - initialize interrupt handling
297  *
298  * @adev: amdgpu device pointer
299  *
300  * Sets up work functions for hotplug and reset interrupts, enables MSI
301  * functionality, initializes vblank, hotplug and reset interrupt handling.
302  *
303  * Returns:
304  * 0 on success or error code on failure
305  */
306 int amdgpu_irq_init(struct amdgpu_device *adev)
307 {
308         int r = 0;
309         unsigned int irq;
310
311         spin_lock_init(&adev->irq.lock);
312
313         /* Enable MSI if not disabled by module parameter */
314         adev->irq.msi_enabled = false;
315
316         if (amdgpu_msi_ok(adev)) {
317                 int nvec = pci_msix_vec_count(adev->pdev);
318                 unsigned int flags;
319
320                 if (nvec <= 0) {
321                         flags = PCI_IRQ_MSI;
322                 } else {
323                         flags = PCI_IRQ_MSI | PCI_IRQ_MSIX;
324                 }
325                 /* we only need one vector */
326                 nvec = pci_alloc_irq_vectors(adev->pdev, 1, 1, flags);
327                 if (nvec > 0) {
328                         adev->irq.msi_enabled = true;
329                         dev_dbg(adev->dev, "using MSI/MSI-X.\n");
330                 }
331         }
332
333         if (!amdgpu_device_has_dc_support(adev)) {
334                 if (!adev->enable_virtual_display)
335                         /* Disable vblank IRQs aggressively for power-saving */
336                         /* XXX: can this be enabled for DC? */
337                         adev_to_drm(adev)->vblank_disable_immediate = true;
338
339                 r = drm_vblank_init(adev_to_drm(adev), adev->mode_info.num_crtc);
340                 if (r)
341                         return r;
342
343                 /* Pre-DCE11 */
344                 INIT_WORK(&adev->hotplug_work,
345                                 amdgpu_hotplug_work_func);
346         }
347
348         INIT_WORK(&adev->irq.ih1_work, amdgpu_irq_handle_ih1);
349         INIT_WORK(&adev->irq.ih2_work, amdgpu_irq_handle_ih2);
350         INIT_WORK(&adev->irq.ih_soft_work, amdgpu_irq_handle_ih_soft);
351
352         /* Use vector 0 for MSI-X. */
353         r = pci_irq_vector(adev->pdev, 0);
354         if (r < 0)
355                 return r;
356         irq = r;
357
358         /* PCI devices require shared interrupts. */
359         r = request_irq(irq, amdgpu_irq_handler, IRQF_SHARED, adev_to_drm(adev)->driver->name,
360                         adev_to_drm(adev));
361         if (r) {
362                 if (!amdgpu_device_has_dc_support(adev))
363                         flush_work(&adev->hotplug_work);
364                 return r;
365         }
366         adev->irq.installed = true;
367         adev->irq.irq = irq;
368         adev_to_drm(adev)->max_vblank_count = 0x00ffffff;
369
370         DRM_DEBUG("amdgpu: irq initialized.\n");
371         return 0;
372 }
373
374
375 void amdgpu_irq_fini_hw(struct amdgpu_device *adev)
376 {
377         if (adev->irq.installed) {
378                 free_irq(adev->irq.irq, adev_to_drm(adev));
379                 adev->irq.installed = false;
380                 if (adev->irq.msi_enabled)
381                         pci_free_irq_vectors(adev->pdev);
382
383                 if (!amdgpu_device_has_dc_support(adev))
384                         flush_work(&adev->hotplug_work);
385         }
386
387         amdgpu_ih_ring_fini(adev, &adev->irq.ih_soft);
388         amdgpu_ih_ring_fini(adev, &adev->irq.ih);
389         amdgpu_ih_ring_fini(adev, &adev->irq.ih1);
390         amdgpu_ih_ring_fini(adev, &adev->irq.ih2);
391 }
392
393 /**
394  * amdgpu_irq_fini - shut down interrupt handling
395  *
396  * @adev: amdgpu device pointer
397  *
398  * Tears down work functions for hotplug and reset interrupts, disables MSI
399  * functionality, shuts down vblank, hotplug and reset interrupt handling,
400  * turns off interrupts from all sources (all ASICs).
401  */
402 void amdgpu_irq_fini_sw(struct amdgpu_device *adev)
403 {
404         unsigned i, j;
405
406         for (i = 0; i < AMDGPU_IRQ_CLIENTID_MAX; ++i) {
407                 if (!adev->irq.client[i].sources)
408                         continue;
409
410                 for (j = 0; j < AMDGPU_MAX_IRQ_SRC_ID; ++j) {
411                         struct amdgpu_irq_src *src = adev->irq.client[i].sources[j];
412
413                         if (!src)
414                                 continue;
415
416                         kfree(src->enabled_types);
417                         src->enabled_types = NULL;
418                 }
419                 kfree(adev->irq.client[i].sources);
420                 adev->irq.client[i].sources = NULL;
421         }
422 }
423
424 /**
425  * amdgpu_irq_add_id - register IRQ source
426  *
427  * @adev: amdgpu device pointer
428  * @client_id: client id
429  * @src_id: source id
430  * @source: IRQ source pointer
431  *
432  * Registers IRQ source on a client.
433  *
434  * Returns:
435  * 0 on success or error code otherwise
436  */
437 int amdgpu_irq_add_id(struct amdgpu_device *adev,
438                       unsigned client_id, unsigned src_id,
439                       struct amdgpu_irq_src *source)
440 {
441         if (client_id >= AMDGPU_IRQ_CLIENTID_MAX)
442                 return -EINVAL;
443
444         if (src_id >= AMDGPU_MAX_IRQ_SRC_ID)
445                 return -EINVAL;
446
447         if (!source->funcs)
448                 return -EINVAL;
449
450         if (!adev->irq.client[client_id].sources) {
451                 adev->irq.client[client_id].sources =
452                         kcalloc(AMDGPU_MAX_IRQ_SRC_ID,
453                                 sizeof(struct amdgpu_irq_src *),
454                                 GFP_KERNEL);
455                 if (!adev->irq.client[client_id].sources)
456                         return -ENOMEM;
457         }
458
459         if (adev->irq.client[client_id].sources[src_id] != NULL)
460                 return -EINVAL;
461
462         if (source->num_types && !source->enabled_types) {
463                 atomic_t *types;
464
465                 types = kcalloc(source->num_types, sizeof(atomic_t),
466                                 GFP_KERNEL);
467                 if (!types)
468                         return -ENOMEM;
469
470                 source->enabled_types = types;
471         }
472
473         adev->irq.client[client_id].sources[src_id] = source;
474         return 0;
475 }
476
477 /**
478  * amdgpu_irq_dispatch - dispatch IRQ to IP blocks
479  *
480  * @adev: amdgpu device pointer
481  * @ih: interrupt ring instance
482  *
483  * Dispatches IRQ to IP blocks.
484  */
485 void amdgpu_irq_dispatch(struct amdgpu_device *adev,
486                          struct amdgpu_ih_ring *ih)
487 {
488         u32 ring_index = ih->rptr >> 2;
489         struct amdgpu_iv_entry entry;
490         unsigned client_id, src_id;
491         struct amdgpu_irq_src *src;
492         bool handled = false;
493         int r;
494
495         entry.ih = ih;
496         entry.iv_entry = (const uint32_t *)&ih->ring[ring_index];
497         amdgpu_ih_decode_iv(adev, &entry);
498
499         trace_amdgpu_iv(ih - &adev->irq.ih, &entry);
500
501         client_id = entry.client_id;
502         src_id = entry.src_id;
503
504         if (client_id >= AMDGPU_IRQ_CLIENTID_MAX) {
505                 DRM_DEBUG("Invalid client_id in IV: %d\n", client_id);
506
507         } else  if (src_id >= AMDGPU_MAX_IRQ_SRC_ID) {
508                 DRM_DEBUG("Invalid src_id in IV: %d\n", src_id);
509
510         } else if ((client_id == AMDGPU_IRQ_CLIENTID_LEGACY) &&
511                    adev->irq.virq[src_id]) {
512                 generic_handle_domain_irq(adev->irq.domain, src_id);
513
514         } else if (!adev->irq.client[client_id].sources) {
515                 DRM_DEBUG("Unregistered interrupt client_id: %d src_id: %d\n",
516                           client_id, src_id);
517
518         } else if ((src = adev->irq.client[client_id].sources[src_id])) {
519                 r = src->funcs->process(adev, src, &entry);
520                 if (r < 0)
521                         DRM_ERROR("error processing interrupt (%d)\n", r);
522                 else if (r)
523                         handled = true;
524
525         } else {
526                 DRM_DEBUG("Unhandled interrupt src_id: %d\n", src_id);
527         }
528
529         /* Send it to amdkfd as well if it isn't already handled */
530         if (!handled)
531                 amdgpu_amdkfd_interrupt(adev, entry.iv_entry);
532 }
533
534 /**
535  * amdgpu_irq_delegate - delegate IV to soft IH ring
536  *
537  * @adev: amdgpu device pointer
538  * @entry: IV entry
539  * @num_dw: size of IV
540  *
541  * Delegate the IV to the soft IH ring and schedule processing of it. Used
542  * if the hardware delegation to IH1 or IH2 doesn't work for some reason.
543  */
544 void amdgpu_irq_delegate(struct amdgpu_device *adev,
545                          struct amdgpu_iv_entry *entry,
546                          unsigned int num_dw)
547 {
548         amdgpu_ih_ring_write(&adev->irq.ih_soft, entry->iv_entry, num_dw);
549         schedule_work(&adev->irq.ih_soft_work);
550 }
551
552 /**
553  * amdgpu_irq_update - update hardware interrupt state
554  *
555  * @adev: amdgpu device pointer
556  * @src: interrupt source pointer
557  * @type: type of interrupt
558  *
559  * Updates interrupt state for the specific source (all ASICs).
560  */
561 int amdgpu_irq_update(struct amdgpu_device *adev,
562                              struct amdgpu_irq_src *src, unsigned type)
563 {
564         unsigned long irqflags;
565         enum amdgpu_interrupt_state state;
566         int r;
567
568         spin_lock_irqsave(&adev->irq.lock, irqflags);
569
570         /* We need to determine after taking the lock, otherwise
571            we might disable just enabled interrupts again */
572         if (amdgpu_irq_enabled(adev, src, type))
573                 state = AMDGPU_IRQ_STATE_ENABLE;
574         else
575                 state = AMDGPU_IRQ_STATE_DISABLE;
576
577         r = src->funcs->set(adev, src, type, state);
578         spin_unlock_irqrestore(&adev->irq.lock, irqflags);
579         return r;
580 }
581
582 /**
583  * amdgpu_irq_gpu_reset_resume_helper - update interrupt states on all sources
584  *
585  * @adev: amdgpu device pointer
586  *
587  * Updates state of all types of interrupts on all sources on resume after
588  * reset.
589  */
590 void amdgpu_irq_gpu_reset_resume_helper(struct amdgpu_device *adev)
591 {
592         int i, j, k;
593
594         if (amdgpu_sriov_vf(adev) || amdgpu_passthrough(adev))
595                 amdgpu_restore_msix(adev);
596
597         for (i = 0; i < AMDGPU_IRQ_CLIENTID_MAX; ++i) {
598                 if (!adev->irq.client[i].sources)
599                         continue;
600
601                 for (j = 0; j < AMDGPU_MAX_IRQ_SRC_ID; ++j) {
602                         struct amdgpu_irq_src *src = adev->irq.client[i].sources[j];
603
604                         if (!src || !src->funcs || !src->funcs->set)
605                                 continue;
606                         for (k = 0; k < src->num_types; k++)
607                                 amdgpu_irq_update(adev, src, k);
608                 }
609         }
610 }
611
612 /**
613  * amdgpu_irq_get - enable interrupt
614  *
615  * @adev: amdgpu device pointer
616  * @src: interrupt source pointer
617  * @type: type of interrupt
618  *
619  * Enables specified type of interrupt on the specified source (all ASICs).
620  *
621  * Returns:
622  * 0 on success or error code otherwise
623  */
624 int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
625                    unsigned type)
626 {
627         if (!adev->irq.installed)
628                 return -ENOENT;
629
630         if (type >= src->num_types)
631                 return -EINVAL;
632
633         if (!src->enabled_types || !src->funcs->set)
634                 return -EINVAL;
635
636         if (atomic_inc_return(&src->enabled_types[type]) == 1)
637                 return amdgpu_irq_update(adev, src, type);
638
639         return 0;
640 }
641
642 /**
643  * amdgpu_irq_put - disable interrupt
644  *
645  * @adev: amdgpu device pointer
646  * @src: interrupt source pointer
647  * @type: type of interrupt
648  *
649  * Enables specified type of interrupt on the specified source (all ASICs).
650  *
651  * Returns:
652  * 0 on success or error code otherwise
653  */
654 int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
655                    unsigned type)
656 {
657         if (!adev->irq.installed)
658                 return -ENOENT;
659
660         if (type >= src->num_types)
661                 return -EINVAL;
662
663         if (!src->enabled_types || !src->funcs->set)
664                 return -EINVAL;
665
666         if (atomic_dec_and_test(&src->enabled_types[type]))
667                 return amdgpu_irq_update(adev, src, type);
668
669         return 0;
670 }
671
672 /**
673  * amdgpu_irq_enabled - check whether interrupt is enabled or not
674  *
675  * @adev: amdgpu device pointer
676  * @src: interrupt source pointer
677  * @type: type of interrupt
678  *
679  * Checks whether the given type of interrupt is enabled on the given source.
680  *
681  * Returns:
682  * *true* if interrupt is enabled, *false* if interrupt is disabled or on
683  * invalid parameters
684  */
685 bool amdgpu_irq_enabled(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
686                         unsigned type)
687 {
688         if (!adev->irq.installed)
689                 return false;
690
691         if (type >= src->num_types)
692                 return false;
693
694         if (!src->enabled_types || !src->funcs->set)
695                 return false;
696
697         return !!atomic_read(&src->enabled_types[type]);
698 }
699
700 /* XXX: Generic IRQ handling */
701 static void amdgpu_irq_mask(struct irq_data *irqd)
702 {
703         /* XXX */
704 }
705
706 static void amdgpu_irq_unmask(struct irq_data *irqd)
707 {
708         /* XXX */
709 }
710
711 /* amdgpu hardware interrupt chip descriptor */
712 static struct irq_chip amdgpu_irq_chip = {
713         .name = "amdgpu-ih",
714         .irq_mask = amdgpu_irq_mask,
715         .irq_unmask = amdgpu_irq_unmask,
716 };
717
718 /**
719  * amdgpu_irqdomain_map - create mapping between virtual and hardware IRQ numbers
720  *
721  * @d: amdgpu IRQ domain pointer (unused)
722  * @irq: virtual IRQ number
723  * @hwirq: hardware irq number
724  *
725  * Current implementation assigns simple interrupt handler to the given virtual
726  * IRQ.
727  *
728  * Returns:
729  * 0 on success or error code otherwise
730  */
731 static int amdgpu_irqdomain_map(struct irq_domain *d,
732                                 unsigned int irq, irq_hw_number_t hwirq)
733 {
734         if (hwirq >= AMDGPU_MAX_IRQ_SRC_ID)
735                 return -EPERM;
736
737         irq_set_chip_and_handler(irq,
738                                  &amdgpu_irq_chip, handle_simple_irq);
739         return 0;
740 }
741
742 /* Implementation of methods for amdgpu IRQ domain */
743 static const struct irq_domain_ops amdgpu_hw_irqdomain_ops = {
744         .map = amdgpu_irqdomain_map,
745 };
746
747 /**
748  * amdgpu_irq_add_domain - create a linear IRQ domain
749  *
750  * @adev: amdgpu device pointer
751  *
752  * Creates an IRQ domain for GPU interrupt sources
753  * that may be driven by another driver (e.g., ACP).
754  *
755  * Returns:
756  * 0 on success or error code otherwise
757  */
758 int amdgpu_irq_add_domain(struct amdgpu_device *adev)
759 {
760         adev->irq.domain = irq_domain_add_linear(NULL, AMDGPU_MAX_IRQ_SRC_ID,
761                                                  &amdgpu_hw_irqdomain_ops, adev);
762         if (!adev->irq.domain) {
763                 DRM_ERROR("GPU irq add domain failed\n");
764                 return -ENODEV;
765         }
766
767         return 0;
768 }
769
770 /**
771  * amdgpu_irq_remove_domain - remove the IRQ domain
772  *
773  * @adev: amdgpu device pointer
774  *
775  * Removes the IRQ domain for GPU interrupt sources
776  * that may be driven by another driver (e.g., ACP).
777  */
778 void amdgpu_irq_remove_domain(struct amdgpu_device *adev)
779 {
780         if (adev->irq.domain) {
781                 irq_domain_remove(adev->irq.domain);
782                 adev->irq.domain = NULL;
783         }
784 }
785
786 /**
787  * amdgpu_irq_create_mapping - create mapping between domain Linux IRQs
788  *
789  * @adev: amdgpu device pointer
790  * @src_id: IH source id
791  *
792  * Creates mapping between a domain IRQ (GPU IH src id) and a Linux IRQ
793  * Use this for components that generate a GPU interrupt, but are driven
794  * by a different driver (e.g., ACP).
795  *
796  * Returns:
797  * Linux IRQ
798  */
799 unsigned amdgpu_irq_create_mapping(struct amdgpu_device *adev, unsigned src_id)
800 {
801         adev->irq.virq[src_id] = irq_create_mapping(adev->irq.domain, src_id);
802
803         return adev->irq.virq[src_id];
804 }