Lines Matching +full:interrupt +full:- +full:driven
30 * DOC: Interrupt Handling
32 * Interrupts generated within GPU hardware raise interrupt requests that are
34 * type of the interrupt and dispatching matching handlers. If handling an
35 * interrupt requires calling kernel functions that may sleep processing is
41 * For GPU interrupt sources that may be driven by another driver, IRQ domain
118 * amdgpu_irq_disable_all - disable *all* interrupts
130 spin_lock_irqsave(&adev->irq.lock, irqflags); in amdgpu_irq_disable_all()
132 if (!adev->irq.client[i].sources) in amdgpu_irq_disable_all()
136 struct amdgpu_irq_src *src = adev->irq.client[i].sources[j]; in amdgpu_irq_disable_all()
138 if (!src || !src->funcs->set || !src->num_types) in amdgpu_irq_disable_all()
141 for (k = 0; k < src->num_types; ++k) { in amdgpu_irq_disable_all()
142 r = src->funcs->set(adev, src, k, in amdgpu_irq_disable_all()
145 dev_err(adev->dev, in amdgpu_irq_disable_all()
146 "error disabling interrupt (%d)\n", in amdgpu_irq_disable_all()
151 spin_unlock_irqrestore(&adev->irq.lock, irqflags); in amdgpu_irq_disable_all()
155 * amdgpu_irq_handler - IRQ handler
171 ret = amdgpu_ih_process(adev, &adev->irq.ih); in amdgpu_irq_handler()
173 pm_runtime_mark_last_busy(dev->dev); in amdgpu_irq_handler()
181 * amdgpu_irq_handle_ih1 - kick of processing for IH1
192 amdgpu_ih_process(adev, &adev->irq.ih1); in amdgpu_irq_handle_ih1()
196 * amdgpu_irq_handle_ih2 - kick of processing for IH2
207 amdgpu_ih_process(adev, &adev->irq.ih2); in amdgpu_irq_handle_ih2()
211 * amdgpu_irq_handle_ih_soft - kick of processing for ih_soft
222 amdgpu_ih_process(adev, &adev->irq.ih_soft); in amdgpu_irq_handle_ih_soft()
226 * amdgpu_msi_ok - check whether MSI functionality is enabled
250 pci_read_config_word(adev->pdev, adev->pdev->msix_cap + PCI_MSIX_FLAGS, &ctrl); in amdgpu_restore_msix()
256 pci_write_config_word(adev->pdev, adev->pdev->msix_cap + PCI_MSIX_FLAGS, ctrl); in amdgpu_restore_msix()
258 pci_write_config_word(adev->pdev, adev->pdev->msix_cap + PCI_MSIX_FLAGS, ctrl); in amdgpu_restore_msix()
262 * amdgpu_irq_init - initialize interrupt handling
267 * functionality, initializes vblank, hotplug and reset interrupt handling.
277 spin_lock_init(&adev->irq.lock); in amdgpu_irq_init()
280 adev->irq.msi_enabled = false; in amdgpu_irq_init()
288 r = pci_alloc_irq_vectors(adev->pdev, 1, 1, flags); in amdgpu_irq_init()
290 dev_err(adev->dev, "Failed to alloc msi vectors\n"); in amdgpu_irq_init()
295 adev->irq.msi_enabled = true; in amdgpu_irq_init()
296 dev_dbg(adev->dev, "using MSI/MSI-X.\n"); in amdgpu_irq_init()
299 INIT_WORK(&adev->irq.ih1_work, amdgpu_irq_handle_ih1); in amdgpu_irq_init()
300 INIT_WORK(&adev->irq.ih2_work, amdgpu_irq_handle_ih2); in amdgpu_irq_init()
301 INIT_WORK(&adev->irq.ih_soft_work, amdgpu_irq_handle_ih_soft); in amdgpu_irq_init()
303 /* Use vector 0 for MSI-X. */ in amdgpu_irq_init()
304 r = pci_irq_vector(adev->pdev, 0); in amdgpu_irq_init()
310 r = request_irq(irq, amdgpu_irq_handler, IRQF_SHARED, adev_to_drm(adev)->driver->name, in amdgpu_irq_init()
315 adev->irq.installed = true; in amdgpu_irq_init()
316 adev->irq.irq = irq; in amdgpu_irq_init()
317 adev_to_drm(adev)->max_vblank_count = 0x00ffffff; in amdgpu_irq_init()
319 dev_dbg(adev->dev, "amdgpu: irq initialized.\n"); in amdgpu_irq_init()
323 if (adev->irq.msi_enabled) in amdgpu_irq_init()
324 pci_free_irq_vectors(adev->pdev); in amdgpu_irq_init()
326 adev->irq.msi_enabled = false; in amdgpu_irq_init()
332 if (adev->irq.installed) { in amdgpu_irq_fini_hw()
333 free_irq(adev->irq.irq, adev_to_drm(adev)); in amdgpu_irq_fini_hw()
334 adev->irq.installed = false; in amdgpu_irq_fini_hw()
335 if (adev->irq.msi_enabled) in amdgpu_irq_fini_hw()
336 pci_free_irq_vectors(adev->pdev); in amdgpu_irq_fini_hw()
339 amdgpu_ih_ring_fini(adev, &adev->irq.ih_soft); in amdgpu_irq_fini_hw()
340 amdgpu_ih_ring_fini(adev, &adev->irq.ih); in amdgpu_irq_fini_hw()
341 amdgpu_ih_ring_fini(adev, &adev->irq.ih1); in amdgpu_irq_fini_hw()
342 amdgpu_ih_ring_fini(adev, &adev->irq.ih2); in amdgpu_irq_fini_hw()
346 * amdgpu_irq_fini_sw - shut down interrupt handling
351 * functionality, shuts down vblank, hotplug and reset interrupt handling,
359 if (!adev->irq.client[i].sources) in amdgpu_irq_fini_sw()
363 struct amdgpu_irq_src *src = adev->irq.client[i].sources[j]; in amdgpu_irq_fini_sw()
368 kfree(src->enabled_types); in amdgpu_irq_fini_sw()
369 src->enabled_types = NULL; in amdgpu_irq_fini_sw()
371 kfree(adev->irq.client[i].sources); in amdgpu_irq_fini_sw()
372 adev->irq.client[i].sources = NULL; in amdgpu_irq_fini_sw()
377 * amdgpu_irq_add_id - register IRQ source
394 return -EINVAL; in amdgpu_irq_add_id()
397 return -EINVAL; in amdgpu_irq_add_id()
399 if (!source->funcs) in amdgpu_irq_add_id()
400 return -EINVAL; in amdgpu_irq_add_id()
402 if (!adev->irq.client[client_id].sources) { in amdgpu_irq_add_id()
403 adev->irq.client[client_id].sources = in amdgpu_irq_add_id()
407 if (!adev->irq.client[client_id].sources) in amdgpu_irq_add_id()
408 return -ENOMEM; in amdgpu_irq_add_id()
411 if (adev->irq.client[client_id].sources[src_id] != NULL) in amdgpu_irq_add_id()
412 return -EINVAL; in amdgpu_irq_add_id()
414 if (source->num_types && !source->enabled_types) { in amdgpu_irq_add_id()
417 types = kcalloc(source->num_types, sizeof(atomic_t), in amdgpu_irq_add_id()
420 return -ENOMEM; in amdgpu_irq_add_id()
422 source->enabled_types = types; in amdgpu_irq_add_id()
425 adev->irq.client[client_id].sources[src_id] = source; in amdgpu_irq_add_id()
430 * amdgpu_irq_dispatch - dispatch IRQ to IP blocks
433 * @ih: interrupt ring instance
440 u32 ring_index = ih->rptr >> 2; in amdgpu_irq_dispatch()
448 entry.iv_entry = (const uint32_t *)&ih->ring[ring_index]; in amdgpu_irq_dispatch()
459 trace_amdgpu_iv(ih - &adev->irq.ih, &entry); in amdgpu_irq_dispatch()
465 dev_dbg(adev->dev, "Invalid client_id in IV: %d\n", client_id); in amdgpu_irq_dispatch()
468 dev_dbg(adev->dev, "Invalid src_id in IV: %d\n", src_id); in amdgpu_irq_dispatch()
472 adev->irq.virq[src_id]) { in amdgpu_irq_dispatch()
473 generic_handle_domain_irq(adev->irq.domain, src_id); in amdgpu_irq_dispatch()
475 } else if (!adev->irq.client[client_id].sources) { in amdgpu_irq_dispatch()
476 dev_dbg(adev->dev, in amdgpu_irq_dispatch()
477 "Unregistered interrupt client_id: %d src_id: %d\n", in amdgpu_irq_dispatch()
480 } else if ((src = adev->irq.client[client_id].sources[src_id])) { in amdgpu_irq_dispatch()
481 r = src->funcs->process(adev, src, &entry); in amdgpu_irq_dispatch()
483 dev_err(adev->dev, "error processing interrupt (%d)\n", in amdgpu_irq_dispatch()
489 dev_dbg(adev->dev, in amdgpu_irq_dispatch()
490 "Unregistered interrupt src_id: %d of client_id:%d\n", in amdgpu_irq_dispatch()
498 if (amdgpu_ih_ts_after(ih->processed_timestamp, entry.timestamp)) in amdgpu_irq_dispatch()
499 ih->processed_timestamp = entry.timestamp; in amdgpu_irq_dispatch()
503 * amdgpu_irq_delegate - delegate IV to soft IH ring
516 amdgpu_ih_ring_write(adev, &adev->irq.ih_soft, entry->iv_entry, num_dw); in amdgpu_irq_delegate()
517 schedule_work(&adev->irq.ih_soft_work); in amdgpu_irq_delegate()
521 * amdgpu_irq_update - update hardware interrupt state
524 * @src: interrupt source pointer
525 * @type: type of interrupt
527 * Updates interrupt state for the specific source (all ASICs).
536 spin_lock_irqsave(&adev->irq.lock, irqflags); in amdgpu_irq_update()
546 r = src->funcs->set(adev, src, type, state); in amdgpu_irq_update()
547 spin_unlock_irqrestore(&adev->irq.lock, irqflags); in amdgpu_irq_update()
552 * amdgpu_irq_gpu_reset_resume_helper - update interrupt states on all sources
567 if (!adev->irq.client[i].sources) in amdgpu_irq_gpu_reset_resume_helper()
571 struct amdgpu_irq_src *src = adev->irq.client[i].sources[j]; in amdgpu_irq_gpu_reset_resume_helper()
573 if (!src || !src->funcs || !src->funcs->set) in amdgpu_irq_gpu_reset_resume_helper()
575 for (k = 0; k < src->num_types; k++) in amdgpu_irq_gpu_reset_resume_helper()
582 * amdgpu_irq_get - enable interrupt
585 * @src: interrupt source pointer
586 * @type: type of interrupt
588 * Enables specified type of interrupt on the specified source (all ASICs).
596 if (!adev->irq.installed) in amdgpu_irq_get()
597 return -ENOENT; in amdgpu_irq_get()
599 if (type >= src->num_types) in amdgpu_irq_get()
600 return -EINVAL; in amdgpu_irq_get()
602 if (!src->enabled_types || !src->funcs->set) in amdgpu_irq_get()
603 return -EINVAL; in amdgpu_irq_get()
605 if (atomic_inc_return(&src->enabled_types[type]) == 1) in amdgpu_irq_get()
612 * amdgpu_irq_put - disable interrupt
615 * @src: interrupt source pointer
616 * @type: type of interrupt
618 * Enables specified type of interrupt on the specified source (all ASICs).
626 /* When the threshold is reached,the interrupt source may not be enabled.return -EINVAL */ in amdgpu_irq_put()
628 return -EINVAL; in amdgpu_irq_put()
630 if (!adev->irq.installed) in amdgpu_irq_put()
631 return -ENOENT; in amdgpu_irq_put()
633 if (type >= src->num_types) in amdgpu_irq_put()
634 return -EINVAL; in amdgpu_irq_put()
636 if (!src->enabled_types || !src->funcs->set) in amdgpu_irq_put()
637 return -EINVAL; in amdgpu_irq_put()
640 return -EINVAL; in amdgpu_irq_put()
642 if (atomic_dec_and_test(&src->enabled_types[type])) in amdgpu_irq_put()
649 * amdgpu_irq_enabled - check whether interrupt is enabled or not
652 * @src: interrupt source pointer
653 * @type: type of interrupt
655 * Checks whether the given type of interrupt is enabled on the given source.
658 * *true* if interrupt is enabled, *false* if interrupt is disabled or on
664 if (!adev->irq.installed) in amdgpu_irq_enabled()
667 if (type >= src->num_types) in amdgpu_irq_enabled()
670 if (!src->enabled_types || !src->funcs->set) in amdgpu_irq_enabled()
673 return !!atomic_read(&src->enabled_types[type]); in amdgpu_irq_enabled()
687 /* amdgpu hardware interrupt chip descriptor */
689 .name = "amdgpu-ih",
695 * amdgpu_irqdomain_map - create mapping between virtual and hardware IRQ numbers
701 * Current implementation assigns simple interrupt handler to the given virtual
711 return -EPERM; in amdgpu_irqdomain_map()
724 * amdgpu_irq_add_domain - create a linear IRQ domain
728 * Creates an IRQ domain for GPU interrupt sources
729 * that may be driven by another driver (e.g., ACP).
736 adev->irq.domain = irq_domain_create_linear(NULL, AMDGPU_MAX_IRQ_SRC_ID, in amdgpu_irq_add_domain()
738 if (!adev->irq.domain) { in amdgpu_irq_add_domain()
739 dev_err(adev->dev, "GPU irq add domain failed\n"); in amdgpu_irq_add_domain()
740 return -ENODEV; in amdgpu_irq_add_domain()
747 * amdgpu_irq_remove_domain - remove the IRQ domain
751 * Removes the IRQ domain for GPU interrupt sources
752 * that may be driven by another driver (e.g., ACP).
756 if (adev->irq.domain) { in amdgpu_irq_remove_domain()
757 irq_domain_remove(adev->irq.domain); in amdgpu_irq_remove_domain()
758 adev->irq.domain = NULL; in amdgpu_irq_remove_domain()
763 * amdgpu_irq_create_mapping - create mapping between domain Linux IRQs
769 * Use this for components that generate a GPU interrupt, but are driven
777 adev->irq.virq[src_id] = irq_create_mapping(adev->irq.domain, src_id); in amdgpu_irq_create_mapping()
779 return adev->irq.virq[src_id]; in amdgpu_irq_create_mapping()