mirror of
https://github.com/UniXNU/NativeAdreno.git
synced 2026-11-08 08:04:59 +03:00
1105b0ec8c
A thread checks the ring every 500 ms as msm's hangcheck_handler does: no fence progress with work pending and no CP progress (a6xx_progress, at most three retries) is a hang. Recovery follows recover_worker: the hung job's VM takes the fault and, unless it is the kernel's, becomes unusable; the fence moves past it; the board's restart hook resets the GPU and runs hw_init and CP init on the same ring; every later job is replayed with its own fence. Clients read the global fault count plus their own VM's, so only the guilty client sees its device lost. The ring gains restart, unfenced submission, a6xx_idle, progress state and the GBIF bus halt; CP init can run unfenced.
63 lines
2.8 KiB
C++
63 lines
2.8 KiB
C++
/* SPDX-License-Identifier: MIT */
|
|
#include "NativeAdrenoCpInit.h"
|
|
#include "AdrenoPM4.h"
|
|
#include <IOKit/IOLib.h>
|
|
|
|
/* Pinned definitions: CP_SQE_INSTR_BASE is the 64-bit register at dword offset
|
|
* 0x0830 for A6XX..A7XX (a6xx.xml). CP_THREAD_CONTROL is opcode 0x17 with
|
|
* CONCURRENT_BIN_DISABLE at bit 27, and CP_ME_INIT is opcode 0x48 with seven
|
|
* payload words (adreno_pm4.xml). The payload values are a7xx_cp_init in
|
|
* a6xx_gpu.c: mask BIT(0)|BIT(1)|BIT(3)|BIT(6)|BIT(8), three hardware
|
|
* contexts, 0x20000000 error detection, 0x00000002 operation mode, the
|
|
* power-up register list address and BIT(31) to read it. */
|
|
enum : uint32_t {
|
|
CpSqeInstrBase = 0x0830,
|
|
CpThreadControlOpcode = 0x17,
|
|
CpMeInitOpcode = 0x48,
|
|
CpConcurrentBinDisable = 1u << 27,
|
|
CpMeInitWords = 8,
|
|
CpInitWords = 10
|
|
};
|
|
IOReturn NativeAdrenoCpInit::poison()
|
|
{
|
|
poisoned_=true;return kIOReturnIOError;
|
|
}
|
|
uint32_t NativeAdrenoCpInit::meInitMask()
|
|
{
|
|
return (1u<<0)|(1u<<1)|(1u<<3)|(1u<<6)|(1u<<8);
|
|
}
|
|
IOReturn NativeAdrenoCpInit::run(const NativeAdrenoRingIo *io,NativeAdrenoRing *ring,
|
|
const NativeAdrenoCpInitConfig *config,uint32_t *fence,bool fenced)
|
|
{
|
|
if(!fence)return kIOReturnBadArgument;*fence=0;
|
|
if(done_ || poisoned_)return kIOReturnNotReady;
|
|
if(!io || !io->write32 || !ring || ring->poisoned())return kIOReturnBadArgument;
|
|
if(!config || !config->sqe_iova || (config->sqe_iova&4095) ||
|
|
config->sqe_iova>=UINT64_C(1)<<48 || !config->pwrup_reglist_iova ||
|
|
(config->pwrup_reglist_iova&3) || config->pwrup_reglist_iova>=UINT64_C(1)<<48)
|
|
return kIOReturnBadArgument;
|
|
if(config->sqe_base_programmed) {
|
|
uint32_t lo=0,hi=0;
|
|
if(!io->read32 || io->read32(io->cookie,CpSqeInstrBase,&lo) || io->read32(io->cookie,CpSqeInstrBase+1,&hi) ||
|
|
(((uint64_t)hi<<32)|lo)!=config->sqe_iova)return poison();
|
|
} else if(io->write32(io->cookie,CpSqeInstrBase,(uint32_t)config->sqe_iova) ||
|
|
io->write32(io->cookie,CpSqeInstrBase+1,(uint32_t)(config->sqe_iova>>32)))
|
|
return poison();
|
|
uint32_t words[CpInitWords]={0};
|
|
if(AdrenoPM4Type7(CpThreadControlOpcode,1,&words[0])!=AdrenoPM4Success ||
|
|
AdrenoPM4Type7(CpMeInitOpcode,7,&words[2])!=AdrenoPM4Success)return poison();
|
|
words[1]=CpConcurrentBinDisable;
|
|
words[3]=meInitMask();
|
|
words[4]=0x00000003; /* hardware contexts */
|
|
words[5]=0x20000000; /* error detection */
|
|
words[6]=0x00000002; /* operation mode */
|
|
words[7]=(uint32_t)config->pwrup_reglist_iova;
|
|
words[8]=(uint32_t)(config->pwrup_reglist_iova>>32);
|
|
words[9]=1u<<31; /* read registers from the list */
|
|
uint32_t value=0;
|
|
const IOReturn status=fenced?ring->submit(words,CpInitWords,&value):ring->submitUnfenced(words,CpInitWords);
|
|
if(status)return poison();
|
|
done_=true;*fence=value;
|
|
return kIOReturnSuccess;
|
|
}
|