linux/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
<<
>>
Prefs
   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_irq.h>
  50#include <drm/drm_vblank.h>
  51#include <drm/amdgpu_drm.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
  68const 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 */
 119static 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 */
 145void 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 */
 186irqreturn_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 */
 221static 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 */
 236static 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 */
 251static 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 */
 270static 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/**
 281 * amdgpu_irq_init - initialize interrupt handling
 282 *
 283 * @adev: amdgpu device pointer
 284 *
 285 * Sets up work functions for hotplug and reset interrupts, enables MSI
 286 * functionality, initializes vblank, hotplug and reset interrupt handling.
 287 *
 288 * Returns:
 289 * 0 on success or error code on failure
 290 */
 291int amdgpu_irq_init(struct amdgpu_device *adev)
 292{
 293        int r = 0;
 294
 295        spin_lock_init(&adev->irq.lock);
 296
 297        /* Enable MSI if not disabled by module parameter */
 298        adev->irq.msi_enabled = false;
 299
 300        if (amdgpu_msi_ok(adev)) {
 301                int nvec = pci_msix_vec_count(adev->pdev);
 302                unsigned int flags;
 303
 304                if (nvec <= 0) {
 305                        flags = PCI_IRQ_MSI;
 306                } else {
 307                        flags = PCI_IRQ_MSI | PCI_IRQ_MSIX;
 308                }
 309                /* we only need one vector */
 310                nvec = pci_alloc_irq_vectors(adev->pdev, 1, 1, flags);
 311                if (nvec > 0) {
 312                        adev->irq.msi_enabled = true;
 313                        dev_dbg(adev->dev, "using MSI/MSI-X.\n");
 314                }
 315        }
 316
 317        if (!amdgpu_device_has_dc_support(adev)) {
 318                if (!adev->enable_virtual_display)
 319                        /* Disable vblank IRQs aggressively for power-saving */
 320                        /* XXX: can this be enabled for DC? */
 321                        adev_to_drm(adev)->vblank_disable_immediate = true;
 322
 323                r = drm_vblank_init(adev_to_drm(adev), adev->mode_info.num_crtc);
 324                if (r)
 325                        return r;
 326
 327                /* Pre-DCE11 */
 328                INIT_WORK(&adev->hotplug_work,
 329                                amdgpu_hotplug_work_func);
 330        }
 331
 332        INIT_WORK(&adev->irq.ih1_work, amdgpu_irq_handle_ih1);
 333        INIT_WORK(&adev->irq.ih2_work, amdgpu_irq_handle_ih2);
 334        INIT_WORK(&adev->irq.ih_soft_work, amdgpu_irq_handle_ih_soft);
 335
 336        adev->irq.installed = true;
 337        /* Use vector 0 for MSI-X */
 338        r = drm_irq_install(adev_to_drm(adev), pci_irq_vector(adev->pdev, 0));
 339        if (r) {
 340                adev->irq.installed = false;
 341                if (!amdgpu_device_has_dc_support(adev))
 342                        flush_work(&adev->hotplug_work);
 343                return r;
 344        }
 345        adev_to_drm(adev)->max_vblank_count = 0x00ffffff;
 346
 347        DRM_DEBUG("amdgpu: irq initialized.\n");
 348        return 0;
 349}
 350
 351/**
 352 * amdgpu_irq_fini - shut down interrupt handling
 353 *
 354 * @adev: amdgpu device pointer
 355 *
 356 * Tears down work functions for hotplug and reset interrupts, disables MSI
 357 * functionality, shuts down vblank, hotplug and reset interrupt handling,
 358 * turns off interrupts from all sources (all ASICs).
 359 */
 360void amdgpu_irq_fini(struct amdgpu_device *adev)
 361{
 362        unsigned i, j;
 363
 364        if (adev->irq.installed) {
 365                drm_irq_uninstall(adev_to_drm(adev));
 366                adev->irq.installed = false;
 367                if (adev->irq.msi_enabled)
 368                        pci_free_irq_vectors(adev->pdev);
 369                if (!amdgpu_device_has_dc_support(adev))
 370                        flush_work(&adev->hotplug_work);
 371        }
 372
 373        for (i = 0; i < AMDGPU_IRQ_CLIENTID_MAX; ++i) {
 374                if (!adev->irq.client[i].sources)
 375                        continue;
 376
 377                for (j = 0; j < AMDGPU_MAX_IRQ_SRC_ID; ++j) {
 378                        struct amdgpu_irq_src *src = adev->irq.client[i].sources[j];
 379
 380                        if (!src)
 381                                continue;
 382
 383                        kfree(src->enabled_types);
 384                        src->enabled_types = NULL;
 385                }
 386                kfree(adev->irq.client[i].sources);
 387                adev->irq.client[i].sources = NULL;
 388        }
 389}
 390
 391/**
 392 * amdgpu_irq_add_id - register IRQ source
 393 *
 394 * @adev: amdgpu device pointer
 395 * @client_id: client id
 396 * @src_id: source id
 397 * @source: IRQ source pointer
 398 *
 399 * Registers IRQ source on a client.
 400 *
 401 * Returns:
 402 * 0 on success or error code otherwise
 403 */
 404int amdgpu_irq_add_id(struct amdgpu_device *adev,
 405                      unsigned client_id, unsigned src_id,
 406                      struct amdgpu_irq_src *source)
 407{
 408        if (client_id >= AMDGPU_IRQ_CLIENTID_MAX)
 409                return -EINVAL;
 410
 411        if (src_id >= AMDGPU_MAX_IRQ_SRC_ID)
 412                return -EINVAL;
 413
 414        if (!source->funcs)
 415                return -EINVAL;
 416
 417        if (!adev->irq.client[client_id].sources) {
 418                adev->irq.client[client_id].sources =
 419                        kcalloc(AMDGPU_MAX_IRQ_SRC_ID,
 420                                sizeof(struct amdgpu_irq_src *),
 421                                GFP_KERNEL);
 422                if (!adev->irq.client[client_id].sources)
 423                        return -ENOMEM;
 424        }
 425
 426        if (adev->irq.client[client_id].sources[src_id] != NULL)
 427                return -EINVAL;
 428
 429        if (source->num_types && !source->enabled_types) {
 430                atomic_t *types;
 431
 432                types = kcalloc(source->num_types, sizeof(atomic_t),
 433                                GFP_KERNEL);
 434                if (!types)
 435                        return -ENOMEM;
 436
 437                source->enabled_types = types;
 438        }
 439
 440        adev->irq.client[client_id].sources[src_id] = source;
 441        return 0;
 442}
 443
 444/**
 445 * amdgpu_irq_dispatch - dispatch IRQ to IP blocks
 446 *
 447 * @adev: amdgpu device pointer
 448 * @ih: interrupt ring instance
 449 *
 450 * Dispatches IRQ to IP blocks.
 451 */
 452void amdgpu_irq_dispatch(struct amdgpu_device *adev,
 453                         struct amdgpu_ih_ring *ih)
 454{
 455        u32 ring_index = ih->rptr >> 2;
 456        struct amdgpu_iv_entry entry;
 457        unsigned client_id, src_id;
 458        struct amdgpu_irq_src *src;
 459        bool handled = false;
 460        int r;
 461
 462        entry.ih = ih;
 463        entry.iv_entry = (const uint32_t *)&ih->ring[ring_index];
 464        amdgpu_ih_decode_iv(adev, &entry);
 465
 466        trace_amdgpu_iv(ih - &adev->irq.ih, &entry);
 467
 468        client_id = entry.client_id;
 469        src_id = entry.src_id;
 470
 471        if (client_id >= AMDGPU_IRQ_CLIENTID_MAX) {
 472                DRM_DEBUG("Invalid client_id in IV: %d\n", client_id);
 473
 474        } else  if (src_id >= AMDGPU_MAX_IRQ_SRC_ID) {
 475                DRM_DEBUG("Invalid src_id in IV: %d\n", src_id);
 476
 477        } else if ((client_id == AMDGPU_IRQ_CLIENTID_LEGACY) &&
 478                   adev->irq.virq[src_id]) {
 479                generic_handle_irq(irq_find_mapping(adev->irq.domain, src_id));
 480
 481        } else if (!adev->irq.client[client_id].sources) {
 482                DRM_DEBUG("Unregistered interrupt client_id: %d src_id: %d\n",
 483                          client_id, src_id);
 484
 485        } else if ((src = adev->irq.client[client_id].sources[src_id])) {
 486                r = src->funcs->process(adev, src, &entry);
 487                if (r < 0)
 488                        DRM_ERROR("error processing interrupt (%d)\n", r);
 489                else if (r)
 490                        handled = true;
 491
 492        } else {
 493                DRM_DEBUG("Unhandled interrupt src_id: %d\n", src_id);
 494        }
 495
 496        /* Send it to amdkfd as well if it isn't already handled */
 497        if (!handled)
 498                amdgpu_amdkfd_interrupt(adev, entry.iv_entry);
 499}
 500
 501/**
 502 * amdgpu_irq_delegate - delegate IV to soft IH ring
 503 *
 504 * @adev: amdgpu device pointer
 505 * @entry: IV entry
 506 * @num_dw: size of IV
 507 *
 508 * Delegate the IV to the soft IH ring and schedule processing of it. Used
 509 * if the hardware delegation to IH1 or IH2 doesn't work for some reason.
 510 */
 511void amdgpu_irq_delegate(struct amdgpu_device *adev,
 512                         struct amdgpu_iv_entry *entry,
 513                         unsigned int num_dw)
 514{
 515        amdgpu_ih_ring_write(&adev->irq.ih_soft, entry->iv_entry, num_dw);
 516        schedule_work(&adev->irq.ih_soft_work);
 517}
 518
 519/**
 520 * amdgpu_irq_update - update hardware interrupt state
 521 *
 522 * @adev: amdgpu device pointer
 523 * @src: interrupt source pointer
 524 * @type: type of interrupt
 525 *
 526 * Updates interrupt state for the specific source (all ASICs).
 527 */
 528int amdgpu_irq_update(struct amdgpu_device *adev,
 529                             struct amdgpu_irq_src *src, unsigned type)
 530{
 531        unsigned long irqflags;
 532        enum amdgpu_interrupt_state state;
 533        int r;
 534
 535        spin_lock_irqsave(&adev->irq.lock, irqflags);
 536
 537        /* We need to determine after taking the lock, otherwise
 538           we might disable just enabled interrupts again */
 539        if (amdgpu_irq_enabled(adev, src, type))
 540                state = AMDGPU_IRQ_STATE_ENABLE;
 541        else
 542                state = AMDGPU_IRQ_STATE_DISABLE;
 543
 544        r = src->funcs->set(adev, src, type, state);
 545        spin_unlock_irqrestore(&adev->irq.lock, irqflags);
 546        return r;
 547}
 548
 549/**
 550 * amdgpu_irq_gpu_reset_resume_helper - update interrupt states on all sources
 551 *
 552 * @adev: amdgpu device pointer
 553 *
 554 * Updates state of all types of interrupts on all sources on resume after
 555 * reset.
 556 */
 557void amdgpu_irq_gpu_reset_resume_helper(struct amdgpu_device *adev)
 558{
 559        int i, j, k;
 560
 561        for (i = 0; i < AMDGPU_IRQ_CLIENTID_MAX; ++i) {
 562                if (!adev->irq.client[i].sources)
 563                        continue;
 564
 565                for (j = 0; j < AMDGPU_MAX_IRQ_SRC_ID; ++j) {
 566                        struct amdgpu_irq_src *src = adev->irq.client[i].sources[j];
 567
 568                        if (!src || !src->funcs || !src->funcs->set)
 569                                continue;
 570                        for (k = 0; k < src->num_types; k++)
 571                                amdgpu_irq_update(adev, src, k);
 572                }
 573        }
 574}
 575
 576/**
 577 * amdgpu_irq_get - enable interrupt
 578 *
 579 * @adev: amdgpu device pointer
 580 * @src: interrupt source pointer
 581 * @type: type of interrupt
 582 *
 583 * Enables specified type of interrupt on the specified source (all ASICs).
 584 *
 585 * Returns:
 586 * 0 on success or error code otherwise
 587 */
 588int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
 589                   unsigned type)
 590{
 591        if (!adev_to_drm(adev)->irq_enabled)
 592                return -ENOENT;
 593
 594        if (type >= src->num_types)
 595                return -EINVAL;
 596
 597        if (!src->enabled_types || !src->funcs->set)
 598                return -EINVAL;
 599
 600        if (atomic_inc_return(&src->enabled_types[type]) == 1)
 601                return amdgpu_irq_update(adev, src, type);
 602
 603        return 0;
 604}
 605
 606/**
 607 * amdgpu_irq_put - disable interrupt
 608 *
 609 * @adev: amdgpu device pointer
 610 * @src: interrupt source pointer
 611 * @type: type of interrupt
 612 *
 613 * Enables specified type of interrupt on the specified source (all ASICs).
 614 *
 615 * Returns:
 616 * 0 on success or error code otherwise
 617 */
 618int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
 619                   unsigned type)
 620{
 621        if (!adev_to_drm(adev)->irq_enabled)
 622                return -ENOENT;
 623
 624        if (type >= src->num_types)
 625                return -EINVAL;
 626
 627        if (!src->enabled_types || !src->funcs->set)
 628                return -EINVAL;
 629
 630        if (atomic_dec_and_test(&src->enabled_types[type]))
 631                return amdgpu_irq_update(adev, src, type);
 632
 633        return 0;
 634}
 635
 636/**
 637 * amdgpu_irq_enabled - check whether interrupt is enabled or not
 638 *
 639 * @adev: amdgpu device pointer
 640 * @src: interrupt source pointer
 641 * @type: type of interrupt
 642 *
 643 * Checks whether the given type of interrupt is enabled on the given source.
 644 *
 645 * Returns:
 646 * *true* if interrupt is enabled, *false* if interrupt is disabled or on
 647 * invalid parameters
 648 */
 649bool amdgpu_irq_enabled(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
 650                        unsigned type)
 651{
 652        if (!adev_to_drm(adev)->irq_enabled)
 653                return false;
 654
 655        if (type >= src->num_types)
 656                return false;
 657
 658        if (!src->enabled_types || !src->funcs->set)
 659                return false;
 660
 661        return !!atomic_read(&src->enabled_types[type]);
 662}
 663
 664/* XXX: Generic IRQ handling */
 665static void amdgpu_irq_mask(struct irq_data *irqd)
 666{
 667        /* XXX */
 668}
 669
 670static void amdgpu_irq_unmask(struct irq_data *irqd)
 671{
 672        /* XXX */
 673}
 674
 675/* amdgpu hardware interrupt chip descriptor */
 676static struct irq_chip amdgpu_irq_chip = {
 677        .name = "amdgpu-ih",
 678        .irq_mask = amdgpu_irq_mask,
 679        .irq_unmask = amdgpu_irq_unmask,
 680};
 681
 682/**
 683 * amdgpu_irqdomain_map - create mapping between virtual and hardware IRQ numbers
 684 *
 685 * @d: amdgpu IRQ domain pointer (unused)
 686 * @irq: virtual IRQ number
 687 * @hwirq: hardware irq number
 688 *
 689 * Current implementation assigns simple interrupt handler to the given virtual
 690 * IRQ.
 691 *
 692 * Returns:
 693 * 0 on success or error code otherwise
 694 */
 695static int amdgpu_irqdomain_map(struct irq_domain *d,
 696                                unsigned int irq, irq_hw_number_t hwirq)
 697{
 698        if (hwirq >= AMDGPU_MAX_IRQ_SRC_ID)
 699                return -EPERM;
 700
 701        irq_set_chip_and_handler(irq,
 702                                 &amdgpu_irq_chip, handle_simple_irq);
 703        return 0;
 704}
 705
 706/* Implementation of methods for amdgpu IRQ domain */
 707static const struct irq_domain_ops amdgpu_hw_irqdomain_ops = {
 708        .map = amdgpu_irqdomain_map,
 709};
 710
 711/**
 712 * amdgpu_irq_add_domain - create a linear IRQ domain
 713 *
 714 * @adev: amdgpu device pointer
 715 *
 716 * Creates an IRQ domain for GPU interrupt sources
 717 * that may be driven by another driver (e.g., ACP).
 718 *
 719 * Returns:
 720 * 0 on success or error code otherwise
 721 */
 722int amdgpu_irq_add_domain(struct amdgpu_device *adev)
 723{
 724        adev->irq.domain = irq_domain_add_linear(NULL, AMDGPU_MAX_IRQ_SRC_ID,
 725                                                 &amdgpu_hw_irqdomain_ops, adev);
 726        if (!adev->irq.domain) {
 727                DRM_ERROR("GPU irq add domain failed\n");
 728                return -ENODEV;
 729        }
 730
 731        return 0;
 732}
 733
 734/**
 735 * amdgpu_irq_remove_domain - remove the IRQ domain
 736 *
 737 * @adev: amdgpu device pointer
 738 *
 739 * Removes the IRQ domain for GPU interrupt sources
 740 * that may be driven by another driver (e.g., ACP).
 741 */
 742void amdgpu_irq_remove_domain(struct amdgpu_device *adev)
 743{
 744        if (adev->irq.domain) {
 745                irq_domain_remove(adev->irq.domain);
 746                adev->irq.domain = NULL;
 747        }
 748}
 749
 750/**
 751 * amdgpu_irq_create_mapping - create mapping between domain Linux IRQs
 752 *
 753 * @adev: amdgpu device pointer
 754 * @src_id: IH source id
 755 *
 756 * Creates mapping between a domain IRQ (GPU IH src id) and a Linux IRQ
 757 * Use this for components that generate a GPU interrupt, but are driven
 758 * by a different driver (e.g., ACP).
 759 *
 760 * Returns:
 761 * Linux IRQ
 762 */
 763unsigned amdgpu_irq_create_mapping(struct amdgpu_device *adev, unsigned src_id)
 764{
 765        adev->irq.virq[src_id] = irq_create_mapping(adev->irq.domain, src_id);
 766
 767        return adev->irq.virq[src_id];
 768}
 769