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