Skip to content

Commit 34db5a3

Browse files
PhilipYangAalexdeucher
authored andcommitted
drm/amdkfd: Queue interrupt work to different CPU
For CPX mode, each KFD node has interrupt worker to process ih_fifo to send events to user space. Currently all interrupt workers of same adev queue to same CPU, all workers execution are actually serialized and this cause KFD ih_fifo overflow when CPU usage is high. Use per-GPU unbounded highpri queue with number of workers equals to number of partitions, let queue_work select the next CPU round robin among the local CPUs of same NUMA. Signed-off-by: Philip Yang <[email protected]> Reviewed-by: Felix Kuehling <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
1 parent 1b00143 commit 34db5a3

File tree

3 files changed

+20
-33
lines changed

3 files changed

+20
-33
lines changed

drivers/gpu/drm/amd/amdkfd/kfd_device.c

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,14 @@ static void kfd_cleanup_nodes(struct kfd_dev *kfd, unsigned int num_nodes)
649649
struct kfd_node *knode;
650650
unsigned int i;
651651

652+
/*
653+
* flush_work ensures that there are no outstanding
654+
* work-queue items that will access interrupt_ring. New work items
655+
* can't be created because we stopped interrupt handling above.
656+
*/
657+
flush_workqueue(kfd->ih_wq);
658+
destroy_workqueue(kfd->ih_wq);
659+
652660
for (i = 0; i < num_nodes; i++) {
653661
knode = kfd->nodes[i];
654662
device_queue_manager_uninit(knode->dqm);
@@ -1066,21 +1074,6 @@ static int kfd_resume(struct kfd_node *node)
10661074
return err;
10671075
}
10681076

1069-
static inline void kfd_queue_work(struct workqueue_struct *wq,
1070-
struct work_struct *work)
1071-
{
1072-
int cpu, new_cpu;
1073-
1074-
cpu = new_cpu = smp_processor_id();
1075-
do {
1076-
new_cpu = cpumask_next(new_cpu, cpu_online_mask) % nr_cpu_ids;
1077-
if (cpu_to_node(new_cpu) == numa_node_id())
1078-
break;
1079-
} while (cpu != new_cpu);
1080-
1081-
queue_work_on(new_cpu, wq, work);
1082-
}
1083-
10841077
/* This is called directly from KGD at ISR. */
10851078
void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry)
10861079
{
@@ -1106,7 +1099,7 @@ void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry)
11061099
patched_ihre, &is_patched)
11071100
&& enqueue_ih_ring_entry(node,
11081101
is_patched ? patched_ihre : ih_ring_entry)) {
1109-
kfd_queue_work(node->ih_wq, &node->interrupt_work);
1102+
queue_work(node->kfd->ih_wq, &node->interrupt_work);
11101103
spin_unlock_irqrestore(&node->interrupt_lock, flags);
11111104
return;
11121105
}

drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,14 @@ int kfd_interrupt_init(struct kfd_node *node)
6262
return r;
6363
}
6464

65-
node->ih_wq = alloc_workqueue("KFD IH", WQ_HIGHPRI, 1);
66-
if (unlikely(!node->ih_wq)) {
67-
kfifo_free(&node->ih_fifo);
68-
dev_err(node->adev->dev, "Failed to allocate KFD IH workqueue\n");
69-
return -ENOMEM;
65+
if (!node->kfd->ih_wq) {
66+
node->kfd->ih_wq = alloc_workqueue("KFD IH", WQ_HIGHPRI | WQ_UNBOUND,
67+
node->kfd->num_nodes);
68+
if (unlikely(!node->kfd->ih_wq)) {
69+
kfifo_free(&node->ih_fifo);
70+
dev_err(node->adev->dev, "Failed to allocate KFD IH workqueue\n");
71+
return -ENOMEM;
72+
}
7073
}
7174
spin_lock_init(&node->interrupt_lock);
7275

@@ -96,16 +99,6 @@ void kfd_interrupt_exit(struct kfd_node *node)
9699
spin_lock_irqsave(&node->interrupt_lock, flags);
97100
node->interrupts_active = false;
98101
spin_unlock_irqrestore(&node->interrupt_lock, flags);
99-
100-
/*
101-
* flush_work ensures that there are no outstanding
102-
* work-queue items that will access interrupt_ring. New work items
103-
* can't be created because we stopped interrupt handling above.
104-
*/
105-
flush_workqueue(node->ih_wq);
106-
107-
destroy_workqueue(node->ih_wq);
108-
109102
kfifo_free(&node->ih_fifo);
110103
}
111104

@@ -155,7 +148,7 @@ static void interrupt_wq(struct work_struct *work)
155148
/* If we spent more than a second processing signals,
156149
* reschedule the worker to avoid soft-lockup warnings
157150
*/
158-
queue_work(dev->ih_wq, &dev->interrupt_work);
151+
queue_work(dev->kfd->ih_wq, &dev->interrupt_work);
159152
break;
160153
}
161154
}

drivers/gpu/drm/amd/amdkfd/kfd_priv.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,6 @@ struct kfd_node {
274274

275275
/* Interrupts */
276276
struct kfifo ih_fifo;
277-
struct workqueue_struct *ih_wq;
278277
struct work_struct interrupt_work;
279278
spinlock_t interrupt_lock;
280279

@@ -367,6 +366,8 @@ struct kfd_dev {
367366
struct kfd_node *nodes[MAX_KFD_NODES];
368367
unsigned int num_nodes;
369368

369+
struct workqueue_struct *ih_wq;
370+
370371
/* Kernel doorbells for KFD device */
371372
struct amdgpu_bo *doorbells;
372373

0 commit comments

Comments
 (0)