Commit 1f896946 authored by Christian König's avatar Christian König Committed by Alex Deucher
Browse files

drm/amdgpu: move more interrupt processing into amdgpu_irq.c



Add a callback to amdgpu_ih_process to remove most of the IV logic.

Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
Acked-by: default avatarHuang Rui <ray.huang@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 95d7fc4a
Loading
Loading
Loading
Loading
+5 −19
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@
#include <drm/drmP.h>
#include "amdgpu.h"
#include "amdgpu_ih.h"
#include "amdgpu_amdkfd.h"

/**
 * amdgpu_ih_ring_init - initialize the IH state
@@ -129,9 +128,10 @@ void amdgpu_ih_ring_fini(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih)
 * Interrupt hander (VI), walk the IH ring.
 * Returns irq process return code.
 */
int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih)
int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
		      void (*callback)(struct amdgpu_device *adev,
				       struct amdgpu_ih_ring *ih))
{
	struct amdgpu_iv_entry entry;
	u32 wptr;

	if (!ih->enabled || adev->shutdown)
@@ -150,24 +150,10 @@ restart_ih:
	rmb();

	while (ih->rptr != wptr) {
		u32 ring_index = ih->rptr >> 2;

		/* Prescreening of high-frequency interrupts */
		if (!amdgpu_ih_prescreen_iv(adev)) {
		callback(adev, ih);
		ih->rptr &= ih->ptr_mask;
			continue;
	}

		/* Before dispatching irq to IP blocks, send it to amdkfd */
		amdgpu_amdkfd_interrupt(adev,
					(const void *) &ih->ring[ring_index]);

		entry.iv_entry = (const uint32_t *)&ih->ring[ring_index];
		amdgpu_ih_decode_iv(adev, &entry);
		ih->rptr &= ih->ptr_mask;

		amdgpu_irq_dispatch(adev, &entry);
	}
	amdgpu_ih_set_rptr(adev);
	atomic_set(&ih->lock, 0);

+3 −1
Original line number Diff line number Diff line
@@ -85,6 +85,8 @@ struct amdgpu_ih_funcs {
int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
			unsigned ring_size, bool use_bus_addr);
void amdgpu_ih_ring_fini(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
		      void (*callback)(struct amdgpu_device *adev,
				       struct amdgpu_ih_ring *ih));

#endif
+30 −1
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@
#include "atom.h"
#include "amdgpu_connectors.h"
#include "amdgpu_trace.h"
#include "amdgpu_amdkfd.h"

#include <linux/pm_runtime.h>

@@ -146,6 +147,34 @@ void amdgpu_irq_disable_all(struct amdgpu_device *adev)
	spin_unlock_irqrestore(&adev->irq.lock, irqflags);
}

/**
 * amdgpu_irq_callback - callback from the IH ring
 *
 * @adev: amdgpu device pointer
 * @ih: amdgpu ih ring
 *
 * Callback from IH ring processing to handle the entry at the current position
 * and advance the read pointer.
 */
static void amdgpu_irq_callback(struct amdgpu_device *adev,
				struct amdgpu_ih_ring *ih)
{
	u32 ring_index = ih->rptr >> 2;
	struct amdgpu_iv_entry entry;

	/* Prescreening of high-frequency interrupts */
	if (!amdgpu_ih_prescreen_iv(adev))
		return;

	/* Before dispatching irq to IP blocks, send it to amdkfd */
	amdgpu_amdkfd_interrupt(adev, (const void *) &ih->ring[ring_index]);

	entry.iv_entry = (const uint32_t *)&ih->ring[ring_index];
	amdgpu_ih_decode_iv(adev, &entry);

	amdgpu_irq_dispatch(adev, &entry);
}

/**
 * amdgpu_irq_handler - IRQ handler
 *
@@ -163,7 +192,7 @@ irqreturn_t amdgpu_irq_handler(int irq, void *arg)
	struct amdgpu_device *adev = dev->dev_private;
	irqreturn_t ret;

	ret = amdgpu_ih_process(adev, &adev->irq.ih);
	ret = amdgpu_ih_process(adev, &adev->irq.ih, amdgpu_irq_callback);
	if (ret == IRQ_HANDLED)
		pm_runtime_mark_last_busy(dev->dev);
	return ret;