drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c
Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c- Extension
.c- Size
- 5486 bytes
- Lines
- 169
- Domain
- Driver Families
- Bucket
- drivers/gpu
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/slab.hlinux/device.hlinux/kfifo.hkfd_priv.h
Detected Declarations
function kfd_interrupt_initfunction kfd_interrupt_exitfunction enqueue_ih_ring_entryfunction dequeue_ih_ring_entryfunction interrupt_wqfunction interrupt_is_wanted
Annotated Snippet
if (unlikely(!node->kfd->ih_wq)) {
kfifo_free(&node->ih_fifo);
dev_err(node->adev->dev, "Failed to allocate KFD IH workqueue\n");
return -ENOMEM;
}
}
spin_lock_init(&node->interrupt_lock);
INIT_WORK(&node->interrupt_work, interrupt_wq);
node->interrupts_active = true;
/*
* After this function returns, the interrupt will be enabled. This
* barrier ensures that the interrupt running on a different processor
* sees all the above writes.
*/
smp_wmb();
return 0;
}
void kfd_interrupt_exit(struct kfd_node *node)
{
/*
* Stop the interrupt handler from writing to the ring and scheduling
* workqueue items. The spinlock ensures that any interrupt running
* after we have unlocked sees interrupts_active = false.
*/
unsigned long flags;
spin_lock_irqsave(&node->interrupt_lock, flags);
node->interrupts_active = false;
spin_unlock_irqrestore(&node->interrupt_lock, flags);
kfifo_free(&node->ih_fifo);
}
/*
* Assumption: single reader/writer. This function is not re-entrant
*/
bool enqueue_ih_ring_entry(struct kfd_node *node, const void *ih_ring_entry)
{
if (kfifo_is_full(&node->ih_fifo)) {
dev_warn_ratelimited(node->adev->dev, "KFD node %d ih_fifo overflow\n",
node->node_id);
return false;
}
kfifo_in(&node->ih_fifo, ih_ring_entry, node->kfd->device_info.ih_ring_entry_size);
return true;
}
/*
* Assumption: single reader/writer. This function is not re-entrant
*/
static bool dequeue_ih_ring_entry(struct kfd_node *node, u32 **ih_ring_entry)
{
int count;
if (kfifo_is_empty(&node->ih_fifo))
return false;
count = kfifo_out_linear_ptr(&node->ih_fifo, ih_ring_entry,
node->kfd->device_info.ih_ring_entry_size);
WARN_ON(count != node->kfd->device_info.ih_ring_entry_size);
return count == node->kfd->device_info.ih_ring_entry_size;
}
static void interrupt_wq(struct work_struct *work)
{
struct kfd_node *dev = container_of(work, struct kfd_node, interrupt_work);
uint32_t *ih_ring_entry;
unsigned long start_jiffies = jiffies;
while (dequeue_ih_ring_entry(dev, &ih_ring_entry)) {
dev->kfd->device_info.event_interrupt_class->interrupt_wq(dev,
ih_ring_entry);
kfifo_skip_count(&dev->ih_fifo, dev->kfd->device_info.ih_ring_entry_size);
if (time_is_before_jiffies(start_jiffies + HZ)) {
/* If we spent more than a second processing signals,
* reschedule the worker to avoid soft-lockup warnings
*/
queue_work(dev->kfd->ih_wq, &dev->interrupt_work);
break;
}
}
}
bool interrupt_is_wanted(struct kfd_node *dev,
Annotation
- Immediate include surface: `linux/slab.h`, `linux/device.h`, `linux/kfifo.h`, `kfd_priv.h`.
- Detected declarations: `function kfd_interrupt_init`, `function kfd_interrupt_exit`, `function enqueue_ih_ring_entry`, `function dequeue_ih_ring_entry`, `function interrupt_wq`, `function interrupt_is_wanted`.
- Atlas domain: Driver Families / drivers/gpu.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.