Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions arch/loongarch/configs/deepin_loongarch_desktop_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_PSI=y
CONFIG_PSI_DEFAULT_DISABLED=y
CONFIG_RCU_EXPERT=y
CONFIG_RCU_BOOST=y
CONFIG_RCU_NOCB_CPU=y
Expand Down Expand Up @@ -3681,6 +3682,7 @@ CONFIG_LOGO=y
CONFIG_DRM_ACCEL=y
CONFIG_SOUND=m
CONFIG_SND=m
CONFIG_SND_UMP=m
CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=m
CONFIG_SND_PCM_OSS=m
Expand All @@ -3689,6 +3691,8 @@ CONFIG_SND_CTL_INPUT_VALIDATION=y
CONFIG_SND_SEQUENCER=m
CONFIG_SND_SEQ_DUMMY=m
CONFIG_SND_SEQUENCER_OSS=m
CONFIG_SND_SEQ_UMP=y
CONFIG_SND_SEQ_UMP_CLIENT=m
CONFIG_SND_DUMMY=m
CONFIG_SND_ALOOP=m
CONFIG_SND_VIRMIDI=m
Expand Down Expand Up @@ -5838,3 +5842,4 @@ CONFIG_RV=y
CONFIG_RV_MON_WWNR=y
# CONFIG_STRICT_DEVMEM is not set
# CONFIG_RUNTIME_TESTING_MENU is not set
# CONFIG_LEGACY_PTYS is not set
7 changes: 6 additions & 1 deletion arch/loongarch/configs/loongson3_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_PSI=y
CONFIG_PSI_DEFAULT_DISABLED=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_IKHEADERS=y
Expand Down Expand Up @@ -832,8 +833,11 @@ CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
CONFIG_LOGO=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_UMP=m
CONFIG_SND_SEQUENCER=m
CONFIG_SND_SEQ_DUMMY=m
CONFIG_SND_SEQ_UMP=y
CONFIG_SND_SEQ_UMP_CLIENT=m
CONFIG_SND_BT87X=m
CONFIG_SND_BT87X_OVERCLOCK=y
CONFIG_SND_HDA_INTEL=y
Expand All @@ -860,7 +864,7 @@ CONFIG_SND_HDA_CODEC_HDMI_ATI=y
CONFIG_SND_HDA_CODEC_HDMI_NVIDIA=y
CONFIG_SND_HDA_CODEC_CONEXANT=y
CONFIG_SND_USB_AUDIO=m
CONFIG_SND_USB_AUDIO_MIDI_V2=y
CONFIG_SND_USB_AUDIO_MIDI_V2=m
CONFIG_SND_SOC=m
CONFIG_SND_SOC_LOONGSON_CARD=m
CONFIG_SND_SOC_ES7134=m
Expand Down Expand Up @@ -1152,3 +1156,4 @@ CONFIG_SCHEDSTATS=y
# CONFIG_DEBUG_PREEMPT is not set
# CONFIG_FTRACE is not set
CONFIG_UNWINDER_ORC=y
# CONFIG_LEGACY_PTYS is not set
5 changes: 5 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1289,6 +1289,11 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
uint64_t seq;
int r;

#ifdef CONFIG_MACH_LOONGSON64
while (amdgpu_ih_fix_is_busy(p->adev))
msleep(20);
Comment on lines +1293 to +1294
#endif

for (i = 0; i < p->gang_size; ++i)
drm_sched_job_arm(&p->jobs[i]->base);

Expand Down
171 changes: 171 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
#include "amdgpu_ih.h"
#include "amdgpu_reset.h"

#ifdef CONFIG_MACH_LOONGSON64
static void amdgpu_ih_handle_fix_work(struct work_struct *work);
#endif

/**
* amdgpu_ih_ring_init - initialize the IH state
*
Expand Down Expand Up @@ -72,6 +76,8 @@ int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
ih->wptr_cpu = &ih->ring[ih->ring_size / 4];
ih->rptr_addr = dma_addr + ih->ring_size + 4;
ih->rptr_cpu = &ih->ring[(ih->ring_size / 4) + 1];


} else {
unsigned wptr_offs, rptr_offs;

Expand Down Expand Up @@ -99,8 +105,18 @@ int amdgpu_ih_ring_init(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih,
ih->wptr_cpu = &adev->wb.wb[wptr_offs];
ih->rptr_addr = adev->wb.gpu_addr + rptr_offs * 4;
ih->rptr_cpu = &adev->wb.wb[rptr_offs];

}

#ifdef CONFIG_MACH_LOONGSON64
INIT_WORK(&ih->fix_work, amdgpu_ih_handle_fix_work);
ih->adev = adev;
atomic_set(&ih->lock, 0);
for (r = 0; r < (ih->ring_size >> 2); r++)
ih->ring[r] = 0xDEADBEFF;
/* ensure data active */
mb();
#endif
init_waitqueue_head(&ih->wait_process);
return 0;
}
Expand All @@ -120,6 +136,10 @@ void amdgpu_ih_ring_fini(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih)
if (!ih->ring)
return;

#ifdef CONFIG_MACH_LOONGSON64
cancel_work_sync(&ih->fix_work);
#endif

if (ih->use_bus_addr) {

/* add 8 bytes for the rptr/wptr shadows and
Expand All @@ -136,6 +156,126 @@ void amdgpu_ih_ring_fini(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih)
}
}

#ifdef CONFIG_MACH_LOONGSON64

int amdgpu_ih_fix_is_busy(struct amdgpu_device *adev)
{
return atomic_read(&adev->irq.cs_lock);
}

static int amdgpu_ih_fix_loongarch_pcie_order_start(struct amdgpu_ih_ring *ih,
u32 rptr, u32 wptr,
bool forever)
{
int i, j;
int check_cnt = 0;
u32 old_wptr, ring_end = ih->ring_size >> 2;

if (rptr == wptr)
return 0;

rptr = rptr >> 2;
wptr = wptr >> 2;
old_wptr = wptr;
wptr = (rptr > wptr) ? ring_end : wptr;

restart_check:
if (!forever && ++check_cnt > 1)
return -ENAVAIL;

if (forever)
msleep(20);

Comment on lines +182 to +188
for (i = rptr; i < wptr; i += 1) {
j = i + 1;
j = (j < wptr) ? j : rptr;
if (le32_to_cpu(ih->ring[i]) == 0xDEADBEFF &&
le32_to_cpu(ih->ring[j]) == 0xDEADBEFF)
goto restart_check;
}

if (rptr > old_wptr) {
for (i = 0; i < old_wptr; i += 1) {
j = i + 1;
j = (j < old_wptr) ? j : 0;
if (le32_to_cpu(ih->ring[i]) == 0xDEADBEFF &&
le32_to_cpu(ih->ring[j]) == 0xDEADBEFF)
goto restart_check;
}
}

return 0;
}

static int amdgpu_ih_fix_loongarch_pcie_order_end(struct amdgpu_ih_ring *ih,
u32 rptr, u32 wptr)
{
int i;
u32 old_wptr, ring_end = ih->ring_size >> 2;

if (rptr == wptr)
return 0;

rptr = rptr >> 2;
wptr = wptr >> 2;
old_wptr = wptr;
wptr = (rptr > wptr) ? ring_end : wptr;

for (i = rptr; i < wptr; i += 1)
ih->ring[i] = 0xDEADBEFF;

if (rptr > old_wptr) {
for (i = 0; i < old_wptr; i += 1)
ih->ring[i] = 0xDEADBEFF;
}
/* memory barrier for writing into ih ring */
mb();
return 0;
}

static void amdgpu_ih_handle_fix_work(struct work_struct *work)
{
struct amdgpu_ih_ring *ih =
container_of(work, struct amdgpu_ih_ring, fix_work);
struct amdgpu_device *adev = ih->adev;

u32 wptr;
u32 old_rptr;
int restart_fg = 0;

restart:
if (restart_fg && atomic_xchg(&ih->lock, 1)) {
atomic_set(&adev->irq.cs_lock, 0);
return;
}

wptr = amdgpu_ih_get_wptr(adev, ih);
/* Order reading of wptr vs. reading of IH ring data */
rmb();

old_rptr = ih->rptr;
amdgpu_ih_fix_loongarch_pcie_order_start(ih, old_rptr, wptr, true);

while (ih->rptr != wptr) {
amdgpu_irq_dispatch(adev, ih);
ih->rptr &= ih->ptr_mask;
}

amdgpu_ih_fix_loongarch_pcie_order_end(ih, old_rptr, ih->rptr);

amdgpu_ih_set_rptr(adev, ih);
atomic_set(&ih->lock, 0);
mb();

if (ih->rptr != amdgpu_ih_get_wptr(adev, ih)) {
restart_fg = 1;
goto restart;
}

atomic_set(&adev->irq.cs_lock, 0);
}
#endif
Comment thread
opsiff marked this conversation as resolved.

/**
* amdgpu_ih_ring_write - write IV to the ring buffer
*
Expand Down Expand Up @@ -210,27 +350,58 @@ int amdgpu_ih_process(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih)
{
unsigned int count;
u32 wptr;
#ifdef CONFIG_MACH_LOONGSON64
u32 old_rptr;
int r;
#endif

if (!ih->enabled || adev->shutdown)
return IRQ_NONE;

wptr = amdgpu_ih_get_wptr(adev, ih);

restart_ih:
#ifdef CONFIG_MACH_LOONGSON64
/* is somebody else already processing irqs? */
if (atomic_xchg(&ih->lock, 1))
return IRQ_NONE;
#endif
count = AMDGPU_IH_MAX_NUM_IVS;
dev_dbg(adev->dev, "%s: rptr %d, wptr %d\n", __func__, ih->rptr, wptr);

/* Order reading of wptr vs. reading of IH ring data */
rmb();

#ifdef CONFIG_MACH_LOONGSON64
old_rptr = ih->rptr;
r = amdgpu_ih_fix_loongarch_pcie_order_start(ih, old_rptr, wptr, false);
if (r) {
if (old_rptr == ((wptr + 16) & ih->ptr_mask) ||
old_rptr == ((wptr + 32) & ih->ptr_mask)) {
atomic_set(&ih->lock, 0);
return IRQ_NONE;
}
atomic_xchg(&adev->irq.cs_lock, 1);
schedule_work(&ih->fix_work);
return IRQ_NONE;
}
#endif

while (ih->rptr != wptr && --count) {
amdgpu_irq_dispatch(adev, ih);
ih->rptr &= ih->ptr_mask;
}

#ifdef CONFIG_MACH_LOONGSON64
amdgpu_ih_fix_loongarch_pcie_order_end(ih, old_rptr, ih->rptr);
#endif

if (!ih->overflow)
amdgpu_ih_set_rptr(adev, ih);

#ifdef CONFIG_MACH_LOONGSON64
atomic_set(&ih->lock, 0);
#endif
wake_up_all(&ih->wait_process);

/* make sure wptr hasn't changed while processing */
Expand Down
8 changes: 8 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_ih.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ struct amdgpu_ih_ring {
wait_queue_head_t wait_process;
uint64_t processed_timestamp;
bool overflow;
#ifdef CONFIG_MACH_LOONGSON64
atomic_t lock;
struct work_struct fix_work;
struct amdgpu_device *adev;
#endif
};

/* return true if time stamp t2 is after t1 with 48bit wrap around */
Expand Down Expand Up @@ -115,4 +120,7 @@ void amdgpu_ih_decode_iv_helper(struct amdgpu_device *adev,
uint64_t amdgpu_ih_decode_iv_ts_helper(struct amdgpu_ih_ring *ih, u32 rptr,
signed int offset);
const char *amdgpu_ih_ring_name(struct amdgpu_device *adev, struct amdgpu_ih_ring *ih);
#ifdef CONFIG_MACH_LOONGSON64
int amdgpu_ih_fix_is_busy(struct amdgpu_device *adev);
#endif
#endif
4 changes: 4 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,10 @@ int amdgpu_irq_init(struct amdgpu_device *adev)

spin_lock_init(&adev->irq.lock);

#ifdef CONFIG_MACH_LOONGSON64
atomic_set(&adev->irq.cs_lock, 0);
#endif

/* Enable MSI if not disabled by module parameter */
adev->irq.msi_enabled = false;

Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ struct amdgpu_irq {
uint32_t srbm_soft_reset;
u32 retry_cam_doorbell_index;
bool retry_cam_enabled;
#ifdef CONFIG_MACH_LOONGSON64
atomic_t cs_lock;
#endif
};

enum interrupt_node_id_per_aid {
Expand Down
Loading
Loading