Something went wrong. Try again.
Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346/* * Copyright 2008 Advanced Micro Devices, Inc. * Copyright 2008 Red Hat Inc. * Copyright 2009 Jerome Glisse. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * */
#include <linux/kthread.h>#include <linux/pci.h>#include <linux/uaccess.h>#include <linux/pm_runtime.h>
#include "amdgpu.h"#include "amdgpu_pm.h"#include "amdgpu_dm_debugfs.h"#include "amdgpu_ras.h"#include "amdgpu_rap.h"#include "amdgpu_securedisplay.h"#include "amdgpu_fw_attestation.h"#include "amdgpu_umr.h"
#include "amdgpu_reset.h"#include "amdgpu_psp_ta.h"#include "amdgpu_userq.h"
#if defined(CONFIG_DEBUG_FS)
/** * amdgpu_debugfs_process_reg_op - Handle MMIO register reads/writes * * @read: True if reading * @f: open file handle * @buf: User buffer to write/read to * @size: Number of bytes to write/read * @pos: Offset to seek to * * This debugfs entry has special meaning on the offset being sought. * Various bits have different meanings: * * Bit 62: Indicates a GRBM bank switch is needed * Bit 61: Indicates a SRBM bank switch is needed (implies bit 62 is * zero) * Bits 24..33: The SE or ME selector if needed * Bits 34..43: The SH (or SA) or PIPE selector if needed * Bits 44..53: The INSTANCE (or CU/WGP) or QUEUE selector if needed * * Bit 23: Indicates that the PM power gating lock should be held * This is necessary to read registers that might be * unreliable during a power gating transistion. * * The lower bits are the BYTE offset of the register to read. This * allows reading multiple registers in a single call and having * the returned size reflect that. */static int amdgpu_debugfs_process_reg_op(bool read, struct file *f, char __user *buf, size_t size, loff_t *pos){ struct amdgpu_device *adev = file_inode(f)->i_private; ssize_t result = 0; int r; bool pm_pg_lock, use_bank, use_ring; unsigned int instance_bank, sh_bank, se_bank, me, pipe, queue, vmid;
pm_pg_lock = use_bank = use_ring = false; instance_bank = sh_bank = se_bank = me = pipe = queue = vmid = 0;
if (size & 0x3 || *pos & 0x3 || ((*pos & (1ULL << 62)) && (*pos & (1ULL << 61)))) return -EINVAL;
/* are we reading registers for which a PG lock is necessary? */ pm_pg_lock = (*pos >> 23) & 1;
if (*pos & (1ULL << 62)) { se_bank = (*pos & GENMASK_ULL(33, 24)) >> 24; sh_bank = (*pos & GENMASK_ULL(43, 34)) >> 34; instance_bank = (*pos & GENMASK_ULL(53, 44)) >> 44;
if (se_bank == 0x3FF) se_bank = 0xFFFFFFFF; if (sh_bank == 0x3FF) sh_bank = 0xFFFFFFFF; if (instance_bank == 0x3FF) instance_bank = 0xFFFFFFFF; use_bank = true; } else if (*pos & (1ULL << 61)) {
me = (*pos & GENMASK_ULL(33, 24)) >> 24; pipe = (*pos & GENMASK_ULL(43, 34)) >> 34; queue = (*pos & GENMASK_ULL(53, 44)) >> 44; vmid = (*pos & GENMASK_ULL(58, 54)) >> 54;
use_ring = true; } else { use_bank = use_ring = false; }
*pos &= (1UL << 22) - 1;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
if (use_bank) { if ((sh_bank != 0xFFFFFFFF && sh_bank >= adev->gfx.config.max_sh_per_se) || (se_bank != 0xFFFFFFFF && se_bank >= adev->gfx.config.max_shader_engines)) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return -EINVAL; } mutex_lock(&adev->grbm_idx_mutex); amdgpu_gfx_select_se_sh(adev, se_bank, sh_bank, instance_bank, 0); } else if (use_ring) { mutex_lock(&adev->srbm_mutex); amdgpu_gfx_select_me_pipe_q(adev, me, pipe, queue, vmid, 0); }
if (pm_pg_lock) mutex_lock(&adev->pm.mutex);
while (size) { uint32_t value;
if (read) { value = RREG32(*pos >> 2); r = put_user(value, (uint32_t *)buf); } else { r = get_user(value, (uint32_t *)buf); if (!r) amdgpu_mm_wreg_mmio_rlc(adev, *pos >> 2, value, 0); } if (r) { result = r; goto end; }
result += 4; buf += 4; *pos += 4; size -= 4; }
end: if (use_bank) { amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0); mutex_unlock(&adev->grbm_idx_mutex); } else if (use_ring) { amdgpu_gfx_select_me_pipe_q(adev, 0, 0, 0, 0, 0); mutex_unlock(&adev->srbm_mutex); }
if (pm_pg_lock) mutex_unlock(&adev->pm.mutex);
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
amdgpu_virt_disable_access_debugfs(adev); return result;}
/* * amdgpu_debugfs_regs_read - Callback for reading MMIO registers */static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf, size_t size, loff_t *pos){ return amdgpu_debugfs_process_reg_op(true, f, buf, size, pos);}
/* * amdgpu_debugfs_regs_write - Callback for writing MMIO registers */static ssize_t amdgpu_debugfs_regs_write(struct file *f, const char __user *buf, size_t size, loff_t *pos){ return amdgpu_debugfs_process_reg_op(false, f, (char __user *)buf, size, pos);}
static int amdgpu_debugfs_regs2_open(struct inode *inode, struct file *file){ struct amdgpu_debugfs_regs2_data *rd;
rd = kzalloc_obj(*rd); if (!rd) return -ENOMEM; rd->adev = file_inode(file)->i_private; file->private_data = rd; mutex_init(&rd->lock);
return 0;}
static int amdgpu_debugfs_regs2_release(struct inode *inode, struct file *file){ struct amdgpu_debugfs_regs2_data *rd = file->private_data;
mutex_destroy(&rd->lock); kfree(file->private_data); return 0;}
static ssize_t amdgpu_debugfs_regs2_op(struct file *f, char __user *buf, u32 offset, size_t size, int write_en){ struct amdgpu_debugfs_regs2_data *rd = f->private_data; struct amdgpu_device *adev = rd->adev; ssize_t result = 0; int r; uint32_t value;
if (size & 0x3 || offset & 0x3) return -EINVAL;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
mutex_lock(&rd->lock);
if (rd->id.use_grbm) { if ((rd->id.grbm.sh != 0xFFFFFFFF && rd->id.grbm.sh >= adev->gfx.config.max_sh_per_se) || (rd->id.grbm.se != 0xFFFFFFFF && rd->id.grbm.se >= adev->gfx.config.max_shader_engines)) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); mutex_unlock(&rd->lock); return -EINVAL; } mutex_lock(&adev->grbm_idx_mutex); amdgpu_gfx_select_se_sh(adev, rd->id.grbm.se, rd->id.grbm.sh, rd->id.grbm.instance, rd->id.xcc_id); }
if (rd->id.use_srbm) { mutex_lock(&adev->srbm_mutex); amdgpu_gfx_select_me_pipe_q(adev, rd->id.srbm.me, rd->id.srbm.pipe, rd->id.srbm.queue, rd->id.srbm.vmid, rd->id.xcc_id); }
if (rd->id.pg_lock) mutex_lock(&adev->pm.mutex);
while (size) { if (!write_en) { value = RREG32(offset >> 2); r = put_user(value, (uint32_t *)buf); } else { r = get_user(value, (uint32_t *)buf); if (!r) amdgpu_mm_wreg_mmio_rlc(adev, offset >> 2, value, rd->id.xcc_id); } if (r) { result = r; goto end; } offset += 4; size -= 4; result += 4; buf += 4; }end: if (rd->id.use_grbm) { amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, rd->id.xcc_id); mutex_unlock(&adev->grbm_idx_mutex); }
if (rd->id.use_srbm) { amdgpu_gfx_select_me_pipe_q(adev, 0, 0, 0, 0, rd->id.xcc_id); mutex_unlock(&adev->srbm_mutex); }
if (rd->id.pg_lock) mutex_unlock(&adev->pm.mutex);
mutex_unlock(&rd->lock);
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
amdgpu_virt_disable_access_debugfs(adev); return result;}
static long amdgpu_debugfs_regs2_ioctl(struct file *f, unsigned int cmd, unsigned long data){ struct amdgpu_debugfs_regs2_data *rd = f->private_data; struct amdgpu_debugfs_regs2_iocdata v1_data; int r;
mutex_lock(&rd->lock);
switch (cmd) { case AMDGPU_DEBUGFS_REGS2_IOC_SET_STATE_V2: r = copy_from_user(&rd->id, (struct amdgpu_debugfs_regs2_iocdata_v2 *)data, sizeof(rd->id)); if (r) r = -EINVAL; goto done; case AMDGPU_DEBUGFS_REGS2_IOC_SET_STATE: r = copy_from_user(&v1_data, (struct amdgpu_debugfs_regs2_iocdata *)data, sizeof(v1_data)); if (r) { r = -EINVAL; goto done; } goto v1_copy; default: r = -EINVAL; goto done; }
v1_copy: rd->id.use_srbm = v1_data.use_srbm; rd->id.use_grbm = v1_data.use_grbm; rd->id.pg_lock = v1_data.pg_lock; rd->id.grbm.se = v1_data.grbm.se; rd->id.grbm.sh = v1_data.grbm.sh; rd->id.grbm.instance = v1_data.grbm.instance; rd->id.srbm.me = v1_data.srbm.me; rd->id.srbm.pipe = v1_data.srbm.pipe; rd->id.srbm.queue = v1_data.srbm.queue; rd->id.xcc_id = 0;done: mutex_unlock(&rd->lock); return r;}
static ssize_t amdgpu_debugfs_regs2_read(struct file *f, char __user *buf, size_t size, loff_t *pos){ return amdgpu_debugfs_regs2_op(f, buf, *pos, size, 0);}
static ssize_t amdgpu_debugfs_regs2_write(struct file *f, const char __user *buf, size_t size, loff_t *pos){ return amdgpu_debugfs_regs2_op(f, (char __user *)buf, *pos, size, 1);}
static int amdgpu_debugfs_gprwave_open(struct inode *inode, struct file *file){ struct amdgpu_debugfs_gprwave_data *rd;
rd = kzalloc_obj(*rd); if (!rd) return -ENOMEM; rd->adev = file_inode(file)->i_private; file->private_data = rd; mutex_init(&rd->lock);
return 0;}
static int amdgpu_debugfs_gprwave_release(struct inode *inode, struct file *file){ struct amdgpu_debugfs_gprwave_data *rd = file->private_data;
mutex_destroy(&rd->lock); kfree(file->private_data); return 0;}
static ssize_t amdgpu_debugfs_gprwave_read(struct file *f, char __user *buf, size_t size, loff_t *pos){ struct amdgpu_debugfs_gprwave_data *rd = f->private_data; struct amdgpu_device *adev = rd->adev; ssize_t result = 0; int r; uint32_t *data, x;
if (size > 4096 || size & 0x3 || *pos & 0x3) return -EINVAL;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
data = kcalloc(1024, sizeof(*data), GFP_KERNEL); if (!data) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return -ENOMEM; }
/* switch to the specific se/sh/cu */ mutex_lock(&adev->grbm_idx_mutex); amdgpu_gfx_select_se_sh(adev, rd->id.se, rd->id.sh, rd->id.cu, rd->id.xcc_id);
if (!rd->id.gpr_or_wave) { x = 0; if (adev->gfx.funcs->read_wave_data) adev->gfx.funcs->read_wave_data(adev, rd->id.xcc_id, rd->id.simd, rd->id.wave, data, &x); } else { x = size >> 2; if (rd->id.gpr.vpgr_or_sgpr) { if (adev->gfx.funcs->read_wave_vgprs) adev->gfx.funcs->read_wave_vgprs(adev, rd->id.xcc_id, rd->id.simd, rd->id.wave, rd->id.gpr.thread, *pos, size>>2, data); } else { if (adev->gfx.funcs->read_wave_sgprs) adev->gfx.funcs->read_wave_sgprs(adev, rd->id.xcc_id, rd->id.simd, rd->id.wave, *pos, size>>2, data); } }
amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, rd->id.xcc_id); mutex_unlock(&adev->grbm_idx_mutex);
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
if (!x) { result = -EINVAL; goto done; }
while (size && (*pos < x * 4)) { uint32_t value;
value = data[*pos >> 2]; r = put_user(value, (uint32_t *)buf); if (r) { result = r; goto done; }
result += 4; buf += 4; *pos += 4; size -= 4; }
done: amdgpu_virt_disable_access_debugfs(adev); kfree(data); return result;}
static long amdgpu_debugfs_gprwave_ioctl(struct file *f, unsigned int cmd, unsigned long data){ struct amdgpu_debugfs_gprwave_data *rd = f->private_data; int r = 0;
mutex_lock(&rd->lock);
switch (cmd) { case AMDGPU_DEBUGFS_GPRWAVE_IOC_SET_STATE: if (copy_from_user(&rd->id, (struct amdgpu_debugfs_gprwave_iocdata *)data, sizeof(rd->id))) r = -EFAULT; goto done; default: r = -EINVAL; goto done; }
done: mutex_unlock(&rd->lock); return r;}
/** * amdgpu_debugfs_regs_pcie_read - Read from a PCIE register * * @f: open file handle * @buf: User buffer to store read data in * @size: Number of bytes to read * @pos: Offset to seek to * * The lower bits are the BYTE offset of the register to read. This * allows reading multiple registers in a single call and having * the returned size reflect that. */static ssize_t amdgpu_debugfs_regs_pcie_read(struct file *f, char __user *buf, size_t size, loff_t *pos){ struct amdgpu_device *adev = file_inode(f)->i_private; ssize_t result = 0; int r;
if (size & 0x3 || *pos & 0x3) return -EINVAL;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
while (size) { uint32_t value;
if (upper_32_bits(*pos)) value = RREG32_PCIE_EXT(*pos); else value = RREG32_PCIE(*pos);
r = put_user(value, (uint32_t *)buf); if (r) goto out;
result += 4; buf += 4; *pos += 4; size -= 4; }
r = result;out: pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return r;}
/** * amdgpu_debugfs_regs_pcie_write - Write to a PCIE register * * @f: open file handle * @buf: User buffer to write data from * @size: Number of bytes to write * @pos: Offset to seek to * * The lower bits are the BYTE offset of the register to write. This * allows writing multiple registers in a single call and having * the returned size reflect that. */static ssize_t amdgpu_debugfs_regs_pcie_write(struct file *f, const char __user *buf, size_t size, loff_t *pos){ struct amdgpu_device *adev = file_inode(f)->i_private; ssize_t result = 0; int r;
if (size & 0x3 || *pos & 0x3) return -EINVAL;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
while (size) { uint32_t value;
r = get_user(value, (uint32_t *)buf); if (r) goto out;
if (upper_32_bits(*pos)) WREG32_PCIE_EXT(*pos, value); else WREG32_PCIE(*pos, value);
result += 4; buf += 4; *pos += 4; size -= 4; }
r = result;out: pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return r;}
/** * amdgpu_debugfs_regs_pcie64_read - Read from a 64-bit PCIE register * * @f: open file handle * @buf: User buffer to store read data in * @size: Number of bytes to read * @pos: Offset to seek to */static ssize_t amdgpu_debugfs_regs_pcie64_read(struct file *f, char __user *buf, size_t size, loff_t *pos){ struct amdgpu_device *adev = file_inode(f)->i_private; ssize_t result = 0; int r;
if (size & 0x7 || *pos & 0x7) return -EINVAL;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
while (size) { uint64_t value;
value = RREG64_PCIE_EXT(*pos);
r = put_user(value, (uint64_t *)buf); if (r) goto out;
result += 8; buf += 8; *pos += 8; size -= 8; }
r = result;out: pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return r;}
/** * amdgpu_debugfs_regs_pcie64_write - Write to a 64-bit PCIE register * * @f: open file handle * @buf: User buffer to write data from * @size: Number of bytes to write * @pos: Offset to seek to */static ssize_t amdgpu_debugfs_regs_pcie64_write(struct file *f, const char __user *buf, size_t size, loff_t *pos){ struct amdgpu_device *adev = file_inode(f)->i_private; ssize_t result = 0; int r;
if (size & 0x7 || *pos & 0x7) return -EINVAL;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
while (size) { uint64_t value;
r = get_user(value, (uint64_t *)buf); if (r) goto out;
WREG64_PCIE_EXT(*pos, value);
result += 8; buf += 8; *pos += 8; size -= 8; }
r = result;out: pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return r;}
/** * amdgpu_debugfs_regs_didt_read - Read from a DIDT register * * @f: open file handle * @buf: User buffer to store read data in * @size: Number of bytes to read * @pos: Offset to seek to * * The lower bits are the BYTE offset of the register to read. This * allows reading multiple registers in a single call and having * the returned size reflect that. */static ssize_t amdgpu_debugfs_regs_didt_read(struct file *f, char __user *buf, size_t size, loff_t *pos){ struct amdgpu_device *adev = file_inode(f)->i_private; ssize_t result = 0; int r;
if (size & 0x3 || *pos & 0x3) return -EINVAL;
if (!adev->reg.didt.rreg) return -EOPNOTSUPP;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
while (size) { uint32_t value;
value = RREG32_DIDT(*pos >> 2); r = put_user(value, (uint32_t *)buf); if (r) goto out;
result += 4; buf += 4; *pos += 4; size -= 4; }
r = result;out: pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return r;}
/** * amdgpu_debugfs_regs_didt_write - Write to a DIDT register * * @f: open file handle * @buf: User buffer to write data from * @size: Number of bytes to write * @pos: Offset to seek to * * The lower bits are the BYTE offset of the register to write. This * allows writing multiple registers in a single call and having * the returned size reflect that. */static ssize_t amdgpu_debugfs_regs_didt_write(struct file *f, const char __user *buf, size_t size, loff_t *pos){ struct amdgpu_device *adev = file_inode(f)->i_private; ssize_t result = 0; int r;
if (size & 0x3 || *pos & 0x3) return -EINVAL;
if (!adev->reg.didt.wreg) return -EOPNOTSUPP;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
while (size) { uint32_t value;
r = get_user(value, (uint32_t *)buf); if (r) goto out;
WREG32_DIDT(*pos >> 2, value);
result += 4; buf += 4; *pos += 4; size -= 4; }
r = result;out: pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return r;}
/** * amdgpu_debugfs_regs_smc_read - Read from a SMC register * * @f: open file handle * @buf: User buffer to store read data in * @size: Number of bytes to read * @pos: Offset to seek to * * The lower bits are the BYTE offset of the register to read. This * allows reading multiple registers in a single call and having * the returned size reflect that. */static ssize_t amdgpu_debugfs_regs_smc_read(struct file *f, char __user *buf, size_t size, loff_t *pos){ struct amdgpu_device *adev = file_inode(f)->i_private; ssize_t result = 0; int r;
if (!adev->reg.smc.rreg) return -EOPNOTSUPP;
if (size & 0x3 || *pos & 0x3) return -EINVAL;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
while (size) { uint32_t value;
value = RREG32_SMC(*pos); r = put_user(value, (uint32_t *)buf); if (r) goto out;
result += 4; buf += 4; *pos += 4; size -= 4; }
r = result;out: pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return r;}
/** * amdgpu_debugfs_regs_smc_write - Write to a SMC register * * @f: open file handle * @buf: User buffer to write data from * @size: Number of bytes to write * @pos: Offset to seek to * * The lower bits are the BYTE offset of the register to write. This * allows writing multiple registers in a single call and having * the returned size reflect that. */static ssize_t amdgpu_debugfs_regs_smc_write(struct file *f, const char __user *buf, size_t size, loff_t *pos){ struct amdgpu_device *adev = file_inode(f)->i_private; ssize_t result = 0; int r;
if (!adev->reg.smc.wreg) return -EOPNOTSUPP;
if (size & 0x3 || *pos & 0x3) return -EINVAL;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
while (size) { uint32_t value;
r = get_user(value, (uint32_t *)buf); if (r) goto out;
WREG32_SMC(*pos, value);
result += 4; buf += 4; *pos += 4; size -= 4; }
r = result;out: pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return r;}
/** * amdgpu_debugfs_gca_config_read - Read from gfx config data * * @f: open file handle * @buf: User buffer to store read data in * @size: Number of bytes to read * @pos: Offset to seek to * * This file is used to access configuration data in a somewhat * stable fashion. The format is a series of DWORDs with the first * indicating which revision it is. New content is appended to the * end so that older software can still read the data. */
static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf, size_t size, loff_t *pos){ struct amdgpu_device *adev = file_inode(f)->i_private; ssize_t result = 0; int r; uint32_t *config, no_regs = 0;
if (size & 0x3 || *pos & 0x3) return -EINVAL;
config = kmalloc_array(256, sizeof(*config), GFP_KERNEL); if (!config) return -ENOMEM;
/* version, increment each time something is added */ config[no_regs++] = 5; config[no_regs++] = adev->gfx.config.max_shader_engines; config[no_regs++] = adev->gfx.config.max_tile_pipes; config[no_regs++] = adev->gfx.config.max_cu_per_sh; config[no_regs++] = adev->gfx.config.max_sh_per_se; config[no_regs++] = adev->gfx.config.max_backends_per_se; config[no_regs++] = adev->gfx.config.max_texture_channel_caches; config[no_regs++] = adev->gfx.config.max_gprs; config[no_regs++] = adev->gfx.config.max_gs_threads; config[no_regs++] = adev->gfx.config.max_hw_contexts; config[no_regs++] = adev->gfx.config.sc_prim_fifo_size_frontend; config[no_regs++] = adev->gfx.config.sc_prim_fifo_size_backend; config[no_regs++] = adev->gfx.config.sc_hiz_tile_fifo_size; config[no_regs++] = adev->gfx.config.sc_earlyz_tile_fifo_size; config[no_regs++] = adev->gfx.config.num_tile_pipes; config[no_regs++] = adev->gfx.config.backend_enable_mask; config[no_regs++] = adev->gfx.config.mem_max_burst_length_bytes; config[no_regs++] = adev->gfx.config.mem_row_size_in_kb; config[no_regs++] = adev->gfx.config.shader_engine_tile_size; config[no_regs++] = adev->gfx.config.num_gpus; config[no_regs++] = adev->gfx.config.multi_gpu_tile_size; config[no_regs++] = adev->gfx.config.mc_arb_ramcfg; config[no_regs++] = adev->gfx.config.gb_addr_config; config[no_regs++] = adev->gfx.config.num_rbs;
/* rev==1 */ config[no_regs++] = adev->rev_id; config[no_regs++] = adev->pg_flags; config[no_regs++] = lower_32_bits(adev->cg_flags);
/* rev==2 */ config[no_regs++] = adev->family; config[no_regs++] = adev->external_rev_id;
/* rev==3 */ config[no_regs++] = adev->pdev->device; config[no_regs++] = adev->pdev->revision; config[no_regs++] = adev->pdev->subsystem_device; config[no_regs++] = adev->pdev->subsystem_vendor;
/* rev==4 APU flag */ config[no_regs++] = adev->flags & AMD_IS_APU ? 1 : 0;
/* rev==5 PG/CG flag upper 32bit */ config[no_regs++] = 0; config[no_regs++] = upper_32_bits(adev->cg_flags);
while (size && (*pos < no_regs * 4)) { uint32_t value;
value = config[*pos >> 2]; r = put_user(value, (uint32_t *)buf); if (r) { kfree(config); return r; }
result += 4; buf += 4; *pos += 4; size -= 4; }
kfree(config); return result;}
/** * amdgpu_debugfs_sensor_read - Read from the powerplay sensors * * @f: open file handle * @buf: User buffer to store read data in * @size: Number of bytes to read * @pos: Offset to seek to * * The offset is treated as the BYTE address of one of the sensors * enumerated in amd/include/kgd_pp_interface.h under the * 'amd_pp_sensors' enumeration. For instance to read the UVD VCLK * you would use the offset 3 * 4 = 12. */static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf, size_t size, loff_t *pos){ struct amdgpu_device *adev = file_inode(f)->i_private; int idx, x, outsize, r, valuesize; uint32_t values[16];
if (size & 3 || *pos & 0x3) return -EINVAL;
if (!adev->pm.dpm_enabled) return -EINVAL;
/* convert offset to sensor number */ idx = *pos >> 2;
valuesize = sizeof(values);
r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
r = amdgpu_dpm_read_sensor(adev, idx, &values[0], &valuesize);
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
if (r) { amdgpu_virt_disable_access_debugfs(adev); return r; }
if (size > valuesize) { amdgpu_virt_disable_access_debugfs(adev); return -EINVAL; }
outsize = 0; x = 0; if (!r) { while (size) { r = put_user(values[x++], (int32_t *)buf); buf += 4; size -= 4; outsize += 4; } }
amdgpu_virt_disable_access_debugfs(adev); return !r ? outsize : r;}
/** amdgpu_debugfs_wave_read - Read WAVE STATUS data * * @f: open file handle * @buf: User buffer to store read data in * @size: Number of bytes to read * @pos: Offset to seek to * * The offset being sought changes which wave that the status data * will be returned for. The bits are used as follows: * * Bits 0..6: Byte offset into data * Bits 7..14: SE selector * Bits 15..22: SH/SA selector * Bits 23..30: CU/{WGP+SIMD} selector * Bits 31..36: WAVE ID selector * Bits 37..44: SIMD ID selector * * The returned data begins with one DWORD of version information * Followed by WAVE STATUS registers relevant to the GFX IP version * being used. See gfx_v8_0_read_wave_data() for an example output. */static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf, size_t size, loff_t *pos){ struct amdgpu_device *adev = f->f_inode->i_private; int r, x; ssize_t result = 0; uint32_t offset, se, sh, cu, wave, simd, data[32];
if (size & 3 || *pos & 3) return -EINVAL;
/* decode offset */ offset = (*pos & GENMASK_ULL(6, 0)); se = (*pos & GENMASK_ULL(14, 7)) >> 7; sh = (*pos & GENMASK_ULL(22, 15)) >> 15; cu = (*pos & GENMASK_ULL(30, 23)) >> 23; wave = (*pos & GENMASK_ULL(36, 31)) >> 31; simd = (*pos & GENMASK_ULL(44, 37)) >> 37;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
/* switch to the specific se/sh/cu */ mutex_lock(&adev->grbm_idx_mutex); amdgpu_gfx_select_se_sh(adev, se, sh, cu, 0);
x = 0; if (adev->gfx.funcs->read_wave_data) adev->gfx.funcs->read_wave_data(adev, 0, simd, wave, data, &x);
amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0); mutex_unlock(&adev->grbm_idx_mutex);
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
if (!x) { amdgpu_virt_disable_access_debugfs(adev); return -EINVAL; }
while (size && (offset < x * 4)) { uint32_t value;
value = data[offset >> 2]; r = put_user(value, (uint32_t *)buf); if (r) { amdgpu_virt_disable_access_debugfs(adev); return r; }
result += 4; buf += 4; offset += 4; size -= 4; }
amdgpu_virt_disable_access_debugfs(adev); return result;}
/** amdgpu_debugfs_gpr_read - Read wave gprs * * @f: open file handle * @buf: User buffer to store read data in * @size: Number of bytes to read * @pos: Offset to seek to * * The offset being sought changes which wave that the status data * will be returned for. The bits are used as follows: * * Bits 0..11: Byte offset into data * Bits 12..19: SE selector * Bits 20..27: SH/SA selector * Bits 28..35: CU/{WGP+SIMD} selector * Bits 36..43: WAVE ID selector * Bits 37..44: SIMD ID selector * Bits 52..59: Thread selector * Bits 60..61: Bank selector (VGPR=0,SGPR=1) * * The return data comes from the SGPR or VGPR register bank for * the selected operational unit. */static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf, size_t size, loff_t *pos){ struct amdgpu_device *adev = f->f_inode->i_private; int r; ssize_t result = 0; uint32_t offset, se, sh, cu, wave, simd, thread, bank, *data;
if (size > 4096 || size & 3 || *pos & 3) return -EINVAL;
/* decode offset */ offset = (*pos & GENMASK_ULL(11, 0)) >> 2; se = (*pos & GENMASK_ULL(19, 12)) >> 12; sh = (*pos & GENMASK_ULL(27, 20)) >> 20; cu = (*pos & GENMASK_ULL(35, 28)) >> 28; wave = (*pos & GENMASK_ULL(43, 36)) >> 36; simd = (*pos & GENMASK_ULL(51, 44)) >> 44; thread = (*pos & GENMASK_ULL(59, 52)) >> 52; bank = (*pos & GENMASK_ULL(61, 60)) >> 60;
data = kcalloc(1024, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) goto err;
r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) goto err;
/* switch to the specific se/sh/cu */ mutex_lock(&adev->grbm_idx_mutex); amdgpu_gfx_select_se_sh(adev, se, sh, cu, 0);
if (bank == 0) { if (adev->gfx.funcs->read_wave_vgprs) adev->gfx.funcs->read_wave_vgprs(adev, 0, simd, wave, thread, offset, size>>2, data); } else { if (adev->gfx.funcs->read_wave_sgprs) adev->gfx.funcs->read_wave_sgprs(adev, 0, simd, wave, offset, size>>2, data); }
amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0); mutex_unlock(&adev->grbm_idx_mutex);
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
while (size) { uint32_t value;
value = data[result >> 2]; r = put_user(value, (uint32_t *)buf); if (r) { amdgpu_virt_disable_access_debugfs(adev); goto err; }
result += 4; buf += 4; size -= 4; }
kfree(data); amdgpu_virt_disable_access_debugfs(adev); return result;
err: pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); kfree(data); return r;}
/** * amdgpu_debugfs_gfxoff_residency_read - Read GFXOFF residency * * @f: open file handle * @buf: User buffer to store read data in * @size: Number of bytes to read * @pos: Offset to seek to * * Read the last residency value logged. It doesn't auto update, one needs to * stop logging before getting the current value. */static ssize_t amdgpu_debugfs_gfxoff_residency_read(struct file *f, char __user *buf, size_t size, loff_t *pos){ struct amdgpu_device *adev = file_inode(f)->i_private; ssize_t result = 0; int r;
if (size & 0x3 || *pos & 0x3) return -EINVAL;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
while (size) { uint32_t value;
r = amdgpu_get_gfx_off_residency(adev, &value); if (r) goto out;
r = put_user(value, (uint32_t *)buf); if (r) goto out;
result += 4; buf += 4; *pos += 4; size -= 4; }
r = result;out: pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
return r;}
/** * amdgpu_debugfs_gfxoff_residency_write - Log GFXOFF Residency * * @f: open file handle * @buf: User buffer to write data from * @size: Number of bytes to write * @pos: Offset to seek to * * Write a 32-bit non-zero to start logging; write a 32-bit zero to stop */static ssize_t amdgpu_debugfs_gfxoff_residency_write(struct file *f, const char __user *buf, size_t size, loff_t *pos){ struct amdgpu_device *adev = file_inode(f)->i_private; ssize_t result = 0; int r;
if (size & 0x3 || *pos & 0x3) return -EINVAL;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
while (size) { u32 value;
r = get_user(value, (uint32_t *)buf); if (r) goto out;
amdgpu_set_gfx_off_residency(adev, value ? true : false);
result += 4; buf += 4; *pos += 4; size -= 4; }
r = result;out: pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
return r;}
/** * amdgpu_debugfs_gfxoff_count_read - Read GFXOFF entry count * * @f: open file handle * @buf: User buffer to store read data in * @size: Number of bytes to read * @pos: Offset to seek to */static ssize_t amdgpu_debugfs_gfxoff_count_read(struct file *f, char __user *buf, size_t size, loff_t *pos){ struct amdgpu_device *adev = file_inode(f)->i_private; ssize_t result = 0; int r;
if (size & 0x3 || *pos & 0x3) return -EINVAL;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
while (size) { u64 value = 0;
r = amdgpu_get_gfx_off_entrycount(adev, &value); if (r) goto out;
r = put_user(value, (u64 *)buf); if (r) goto out;
result += 4; buf += 4; *pos += 4; size -= 4; }
r = result;out: pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
return r;}
/** * amdgpu_debugfs_gfxoff_write - Enable/disable GFXOFF * * @f: open file handle * @buf: User buffer to write data from * @size: Number of bytes to write * @pos: Offset to seek to * * Write a 32-bit zero to disable or a 32-bit non-zero to enable */static ssize_t amdgpu_debugfs_gfxoff_write(struct file *f, const char __user *buf, size_t size, loff_t *pos){ struct amdgpu_device *adev = file_inode(f)->i_private; ssize_t result = 0; int r;
if (size & 0x3 || *pos & 0x3) return -EINVAL;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
while (size) { uint32_t value;
r = get_user(value, (uint32_t *)buf); if (r) goto out;
amdgpu_gfx_off_ctrl(adev, value ? true : false);
result += 4; buf += 4; *pos += 4; size -= 4; }
r = result;out: pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
return r;}
/** * amdgpu_debugfs_gfxoff_read - read gfxoff status * * @f: open file handle * @buf: User buffer to store read data in * @size: Number of bytes to read * @pos: Offset to seek to */static ssize_t amdgpu_debugfs_gfxoff_read(struct file *f, char __user *buf, size_t size, loff_t *pos){ struct amdgpu_device *adev = file_inode(f)->i_private; ssize_t result = 0; int r;
if (size & 0x3 || *pos & 0x3) return -EINVAL;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
while (size) { u32 value = adev->gfx.gfx_off_state;
r = put_user(value, (u32 *)buf); if (r) goto out;
result += 4; buf += 4; *pos += 4; size -= 4; }
r = result;out: pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
return r;}
static ssize_t amdgpu_debugfs_gfxoff_status_read(struct file *f, char __user *buf, size_t size, loff_t *pos){ struct amdgpu_device *adev = file_inode(f)->i_private; ssize_t result = 0; int r;
if (size & 0x3 || *pos & 0x3) return -EINVAL;
r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; }
while (size) { u32 value;
r = amdgpu_get_gfx_off_status(adev, &value); if (r) goto out;
r = put_user(value, (u32 *)buf); if (r) goto out;
result += 4; buf += 4; *pos += 4; size -= 4; }
r = result;out: pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
return r;}
static const struct file_operations amdgpu_debugfs_regs2_fops = { .owner = THIS_MODULE, .unlocked_ioctl = amdgpu_debugfs_regs2_ioctl, .read = amdgpu_debugfs_regs2_read, .write = amdgpu_debugfs_regs2_write, .open = amdgpu_debugfs_regs2_open, .release = amdgpu_debugfs_regs2_release, .llseek = default_llseek};
static const struct file_operations amdgpu_debugfs_gprwave_fops = { .owner = THIS_MODULE, .unlocked_ioctl = amdgpu_debugfs_gprwave_ioctl, .read = amdgpu_debugfs_gprwave_read, .open = amdgpu_debugfs_gprwave_open, .release = amdgpu_debugfs_gprwave_release, .llseek = default_llseek};
static const struct file_operations amdgpu_debugfs_regs_fops = { .owner = THIS_MODULE, .read = amdgpu_debugfs_regs_read, .write = amdgpu_debugfs_regs_write, .llseek = default_llseek};static const struct file_operations amdgpu_debugfs_regs_didt_fops = { .owner = THIS_MODULE, .read = amdgpu_debugfs_regs_didt_read, .write = amdgpu_debugfs_regs_didt_write, .llseek = default_llseek};static const struct file_operations amdgpu_debugfs_regs_pcie_fops = { .owner = THIS_MODULE, .read = amdgpu_debugfs_regs_pcie_read, .write = amdgpu_debugfs_regs_pcie_write, .llseek = default_llseek};static const struct file_operations amdgpu_debugfs_regs_pcie64_fops = { .owner = THIS_MODULE, .read = amdgpu_debugfs_regs_pcie64_read, .write = amdgpu_debugfs_regs_pcie64_write, .llseek = default_llseek};static const struct file_operations amdgpu_debugfs_regs_smc_fops = { .owner = THIS_MODULE, .read = amdgpu_debugfs_regs_smc_read, .write = amdgpu_debugfs_regs_smc_write, .llseek = default_llseek};
static const struct file_operations amdgpu_debugfs_gca_config_fops = { .owner = THIS_MODULE, .read = amdgpu_debugfs_gca_config_read, .llseek = default_llseek};
static const struct file_operations amdgpu_debugfs_sensors_fops = { .owner = THIS_MODULE, .read = amdgpu_debugfs_sensor_read, .llseek = default_llseek};
static const struct file_operations amdgpu_debugfs_wave_fops = { .owner = THIS_MODULE, .read = amdgpu_debugfs_wave_read, .llseek = default_llseek};static const struct file_operations amdgpu_debugfs_gpr_fops = { .owner = THIS_MODULE, .read = amdgpu_debugfs_gpr_read, .llseek = default_llseek};
static const struct file_operations amdgpu_debugfs_gfxoff_fops = { .owner = THIS_MODULE, .read = amdgpu_debugfs_gfxoff_read, .write = amdgpu_debugfs_gfxoff_write, .llseek = default_llseek};
static const struct file_operations amdgpu_debugfs_gfxoff_status_fops = { .owner = THIS_MODULE, .read = amdgpu_debugfs_gfxoff_status_read, .llseek = default_llseek};
static const struct file_operations amdgpu_debugfs_gfxoff_count_fops = { .owner = THIS_MODULE, .read = amdgpu_debugfs_gfxoff_count_read, .llseek = default_llseek};
static const struct file_operations amdgpu_debugfs_gfxoff_residency_fops = { .owner = THIS_MODULE, .read = amdgpu_debugfs_gfxoff_residency_read, .write = amdgpu_debugfs_gfxoff_residency_write, .llseek = default_llseek};
static const struct file_operations *debugfs_regs[] = { &amdgpu_debugfs_regs_fops, &amdgpu_debugfs_regs2_fops, &amdgpu_debugfs_gprwave_fops, &amdgpu_debugfs_regs_didt_fops, &amdgpu_debugfs_regs_pcie_fops, &amdgpu_debugfs_regs_pcie64_fops, &amdgpu_debugfs_regs_smc_fops, &amdgpu_debugfs_gca_config_fops, &amdgpu_debugfs_sensors_fops, &amdgpu_debugfs_wave_fops, &amdgpu_debugfs_gpr_fops, &amdgpu_debugfs_gfxoff_fops, &amdgpu_debugfs_gfxoff_status_fops, &amdgpu_debugfs_gfxoff_count_fops, &amdgpu_debugfs_gfxoff_residency_fops,};
static const char * const debugfs_regs_names[] = { "amdgpu_regs", "amdgpu_regs2", "amdgpu_gprwave", "amdgpu_regs_didt", "amdgpu_regs_pcie", "amdgpu_regs_pcie64", "amdgpu_regs_smc", "amdgpu_gca_config", "amdgpu_sensors", "amdgpu_wave", "amdgpu_gpr", "amdgpu_gfxoff", "amdgpu_gfxoff_status", "amdgpu_gfxoff_count", "amdgpu_gfxoff_residency",};
/** * amdgpu_debugfs_regs_init - Initialize debugfs entries that provide * register access. * * @adev: The device to attach the debugfs entries to */int amdgpu_debugfs_regs_init(struct amdgpu_device *adev){ struct drm_minor *minor = adev_to_drm(adev)->primary; struct dentry *ent, *root = minor->debugfs_root; unsigned int i;
for (i = 0; i < ARRAY_SIZE(debugfs_regs); i++) { ent = debugfs_create_file(debugfs_regs_names[i], S_IFREG | 0400, root, adev, debugfs_regs[i]); if (!i && !IS_ERR_OR_NULL(ent)) i_size_write(ent->d_inode, adev->rmmio_size); }
return 0;}
static int amdgpu_debugfs_test_ib_show(struct seq_file *m, void *unused){ struct amdgpu_device *adev = m->private; struct drm_device *dev = adev_to_drm(adev); int r = 0, i;
r = pm_runtime_get_sync(dev->dev); if (r < 0) { pm_runtime_put_autosuspend(dev->dev); return r; }
/* Avoid accidently unparking the sched thread during GPU reset */ r = down_write_killable(&adev->reset_domain->sem); if (r) return r;
/* hold on the scheduler */ for (i = 0; i < AMDGPU_MAX_RINGS; i++) { struct amdgpu_ring *ring = adev->rings[i];
if (!amdgpu_ring_sched_ready(ring)) continue; drm_sched_wqueue_stop(&ring->sched); }
seq_puts(m, "run ib test:\n"); r = amdgpu_ib_ring_tests(adev); if (r) seq_printf(m, "ib ring tests failed (%d).\n", r); else seq_puts(m, "ib ring tests passed.\n");
/* go on the scheduler */ for (i = 0; i < AMDGPU_MAX_RINGS; i++) { struct amdgpu_ring *ring = adev->rings[i];
if (!amdgpu_ring_sched_ready(ring)) continue; drm_sched_wqueue_start(&ring->sched); }
up_write(&adev->reset_domain->sem);
pm_runtime_put_autosuspend(dev->dev);
return 0;}
static int amdgpu_debugfs_evict_vram(void *data, u64 *val){ struct amdgpu_device *adev = (struct amdgpu_device *)data; struct drm_device *dev = adev_to_drm(adev); int r;
r = pm_runtime_get_sync(dev->dev); if (r < 0) { pm_runtime_put_autosuspend(dev->dev); return r; }
*val = amdgpu_ttm_evict_resources(adev, TTM_PL_VRAM);
pm_runtime_put_autosuspend(dev->dev);
return 0;}
static int amdgpu_debugfs_evict_gtt(void *data, u64 *val){ struct amdgpu_device *adev = (struct amdgpu_device *)data; struct drm_device *dev = adev_to_drm(adev); int r;
r = pm_runtime_get_sync(dev->dev); if (r < 0) { pm_runtime_put_autosuspend(dev->dev); return r; }
*val = amdgpu_ttm_evict_resources(adev, TTM_PL_TT);
pm_runtime_put_autosuspend(dev->dev);
return 0;}
static int amdgpu_debugfs_benchmark(void *data, u64 val){ struct amdgpu_device *adev = (struct amdgpu_device *)data; struct drm_device *dev = adev_to_drm(adev); int r;
r = pm_runtime_get_sync(dev->dev); if (r < 0) { pm_runtime_put_autosuspend(dev->dev); return r; }
r = amdgpu_benchmark(adev, val);
pm_runtime_put_autosuspend(dev->dev);
return r;}
static int amdgpu_debugfs_vm_info_show(struct seq_file *m, void *unused){ struct amdgpu_device *adev = m->private; struct drm_device *dev = adev_to_drm(adev); struct drm_file *file; int r;
r = mutex_lock_interruptible(&dev->filelist_mutex); if (r) return r;
list_for_each_entry(file, &dev->filelist, lhead) { struct amdgpu_fpriv *fpriv = file->driver_priv; struct amdgpu_vm *vm = &fpriv->vm; struct amdgpu_task_info *ti;
ti = amdgpu_vm_get_task_info_vm(vm); if (ti) { seq_printf(m, "pid:%d\tProcess:%s ----------\n", ti->task.pid, ti->process_name); amdgpu_vm_put_task_info(ti); }
r = amdgpu_bo_reserve(vm->root.bo, true); if (r) break; amdgpu_debugfs_vm_bo_info(vm, m); amdgpu_bo_unreserve(vm->root.bo); }
mutex_unlock(&dev->filelist_mutex);
return r;}
DEFINE_SHOW_ATTRIBUTE(amdgpu_debugfs_test_ib);DEFINE_SHOW_ATTRIBUTE(amdgpu_debugfs_vm_info);DEFINE_DEBUGFS_ATTRIBUTE(amdgpu_evict_vram_fops, amdgpu_debugfs_evict_vram, NULL, "%lld\n");DEFINE_DEBUGFS_ATTRIBUTE(amdgpu_evict_gtt_fops, amdgpu_debugfs_evict_gtt, NULL, "%lld\n");DEFINE_DEBUGFS_ATTRIBUTE(amdgpu_benchmark_fops, NULL, amdgpu_debugfs_benchmark, "%lld\n");
static void amdgpu_ib_preempt_fences_swap(struct amdgpu_ring *ring, struct dma_fence **fences){ struct amdgpu_fence_driver *drv = &ring->fence_drv; uint32_t sync_seq, last_seq;
last_seq = atomic_read(&ring->fence_drv.last_seq); sync_seq = ring->fence_drv.sync_seq;
last_seq &= drv->num_fences_mask; sync_seq &= drv->num_fences_mask;
do { struct dma_fence *fence, **ptr;
++last_seq; last_seq &= drv->num_fences_mask; ptr = &drv->fences[last_seq];
fence = rcu_dereference_protected(*ptr, 1); RCU_INIT_POINTER(*ptr, NULL);
if (!fence) continue;
fences[last_seq] = fence;
} while (last_seq != sync_seq);}
static void amdgpu_ib_preempt_signal_fences(struct dma_fence **fences, int length){ int i; struct dma_fence *fence;
for (i = 0; i < length; i++) { fence = fences[i]; if (!fence) continue; dma_fence_signal(fence); dma_fence_put(fence); }}
static void amdgpu_ib_preempt_job_recovery(struct drm_gpu_scheduler *sched){ struct drm_sched_job *s_job; struct dma_fence *fence;
spin_lock(&sched->job_list_lock); list_for_each_entry(s_job, &sched->pending_list, list) { fence = sched->ops->run_job(s_job); dma_fence_put(fence); } spin_unlock(&sched->job_list_lock);}
static void amdgpu_ib_preempt_mark_partial_job(struct amdgpu_ring *ring){ struct amdgpu_job *job; struct drm_sched_job *s_job, *tmp; uint32_t preempt_seq; struct dma_fence *fence, **ptr; struct amdgpu_fence_driver *drv = &ring->fence_drv; struct drm_gpu_scheduler *sched = &ring->sched; bool preempted = true;
if (ring->funcs->type != AMDGPU_RING_TYPE_GFX) return;
preempt_seq = le32_to_cpu(*(drv->cpu_addr + 2)); if (preempt_seq <= atomic_read(&drv->last_seq)) { preempted = false; goto no_preempt; }
preempt_seq &= drv->num_fences_mask; ptr = &drv->fences[preempt_seq]; fence = rcu_dereference_protected(*ptr, 1);
no_preempt: spin_lock(&sched->job_list_lock); list_for_each_entry_safe(s_job, tmp, &sched->pending_list, list) { if (dma_fence_is_signaled(&s_job->s_fence->finished)) { /* remove job from ring_mirror_list */ list_del_init(&s_job->list); sched->ops->free_job(s_job); continue; } job = to_amdgpu_job(s_job); if (preempted && (&job->hw_fence->base) == fence) /* mark the job as preempted */ job->preemption_status |= AMDGPU_IB_PREEMPTED; } spin_unlock(&sched->job_list_lock);}
static int amdgpu_debugfs_ib_preempt(void *data, u64 val){ int r, length; struct amdgpu_ring *ring; struct dma_fence **fences = NULL; struct amdgpu_device *adev = (struct amdgpu_device *)data;
if (val >= AMDGPU_MAX_RINGS) return -EINVAL;
ring = adev->rings[val];
if (!amdgpu_ring_sched_ready(ring) || !ring->funcs->preempt_ib) return -EINVAL;
/* the last preemption failed */ if (ring->trail_seq != le32_to_cpu(*ring->trail_fence_cpu_addr)) return -EBUSY;
length = ring->fence_drv.num_fences_mask + 1; fences = kcalloc(length, sizeof(void *), GFP_KERNEL); if (!fences) return -ENOMEM;
/* Avoid accidently unparking the sched thread during GPU reset */ r = down_read_killable(&adev->reset_domain->sem); if (r) goto pro_end;
/* stop the scheduler */ drm_sched_wqueue_stop(&ring->sched);
/* preempt the IB */ r = amdgpu_ring_preempt_ib(ring); if (r) { drm_warn(adev_to_drm(adev), "failed to preempt ring %d\n", ring->idx); goto failure; }
amdgpu_fence_process(ring);
if (atomic_read(&ring->fence_drv.last_seq) != ring->fence_drv.sync_seq) { drm_info(adev_to_drm(adev), "ring %d was preempted\n", ring->idx);
amdgpu_ib_preempt_mark_partial_job(ring);
/* swap out the old fences */ amdgpu_ib_preempt_fences_swap(ring, fences);
amdgpu_fence_driver_force_completion(ring, NULL);
/* resubmit unfinished jobs */ amdgpu_ib_preempt_job_recovery(&ring->sched);
/* wait for jobs finished */ amdgpu_fence_wait_empty(ring);
/* signal the old fences */ amdgpu_ib_preempt_signal_fences(fences, length); }
failure: /* restart the scheduler */ drm_sched_wqueue_start(&ring->sched);
up_read(&adev->reset_domain->sem);
pro_end: kfree(fences);
return r;}
static int amdgpu_debugfs_sclk_set(void *data, u64 val){ int ret = 0; uint32_t max_freq, min_freq; struct amdgpu_device *adev = (struct amdgpu_device *)data;
if (amdgpu_sriov_multi_vf_mode(adev)) return -EINVAL;
ret = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (ret < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return ret; }
ret = amdgpu_dpm_get_dpm_freq_range(adev, PP_SCLK, &min_freq, &max_freq); if (ret == -EOPNOTSUPP) { ret = 0; goto out; } if (ret || val > max_freq || val < min_freq) { ret = -EINVAL; goto out; }
ret = amdgpu_dpm_set_soft_freq_range(adev, PP_SCLK, (uint32_t)val, (uint32_t)val); if (ret) ret = -EINVAL;
out: pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
return ret;}
DEFINE_DEBUGFS_ATTRIBUTE(fops_ib_preempt, NULL, amdgpu_debugfs_ib_preempt, "%llu\n");
DEFINE_DEBUGFS_ATTRIBUTE(fops_sclk_set, NULL, amdgpu_debugfs_sclk_set, "%llu\n");
int amdgpu_debugfs_init(struct amdgpu_device *adev){ struct dentry *root = adev_to_drm(adev)->primary->debugfs_root; struct dentry *ent; int r, i;
if (!debugfs_initialized()) return 0;
debugfs_create_x32("amdgpu_smu_debug", 0600, root, &adev->pm.smu_debug_mask);
debugfs_create_x64("unique_id", 0444, root, &adev->unique_id); debugfs_create_x8("unitid", 0444, root, &adev->unitid);
ent = debugfs_create_file("amdgpu_preempt_ib", 0600, root, adev, &fops_ib_preempt); if (IS_ERR(ent)) { drm_err(adev_to_drm(adev), "unable to create amdgpu_preempt_ib debugsfs file\n"); return PTR_ERR(ent); }
ent = debugfs_create_file("amdgpu_force_sclk", 0200, root, adev, &fops_sclk_set); if (IS_ERR(ent)) { drm_err(adev_to_drm(adev), "unable to create amdgpu_set_sclk debugsfs file\n"); return PTR_ERR(ent); }
/* Register debugfs entries for amdgpu_ttm */ amdgpu_ttm_debugfs_init(adev); amdgpu_debugfs_pm_init(adev); amdgpu_debugfs_sa_init(adev); amdgpu_debugfs_fence_init(adev); amdgpu_debugfs_gem_init(adev);
r = amdgpu_debugfs_regs_init(adev); if (r) drm_err(adev_to_drm(adev), "registering register debugfs failed (%d).\n", r);
amdgpu_debugfs_firmware_init(adev); amdgpu_ta_if_debugfs_init(adev);
amdgpu_debugfs_mes_event_log_init(adev);
#if defined(CONFIG_DRM_AMD_DC) if (adev->dc_enabled) dtn_debugfs_init(adev);#endif
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { struct amdgpu_ring *ring = adev->rings[i];
if (!ring) continue;
amdgpu_debugfs_ring_init(adev, ring); }
for (i = 0; i < adev->vcn.num_vcn_inst; i++) { if (!amdgpu_vcnfw_log) break;
if (adev->vcn.harvest_config & (1 << i)) continue;
amdgpu_debugfs_vcn_fwlog_init(adev, i, &adev->vcn.inst[i]); }
if (amdgpu_umsch_mm & amdgpu_umsch_mm_fwlog) amdgpu_debugfs_umsch_fwlog_init(adev, &adev->umsch_mm);
amdgpu_debugfs_vcn_sched_mask_init(adev); amdgpu_debugfs_jpeg_sched_mask_init(adev); amdgpu_debugfs_gfx_sched_mask_init(adev); amdgpu_debugfs_compute_sched_mask_init(adev); amdgpu_debugfs_sdma_sched_mask_init(adev);
amdgpu_ras_debugfs_create_all(adev); amdgpu_rap_debugfs_init(adev); amdgpu_securedisplay_debugfs_init(adev); amdgpu_fw_attestation_debugfs_init(adev); amdgpu_psp_debugfs_init(adev);
debugfs_create_file("amdgpu_evict_vram", 0400, root, adev, &amdgpu_evict_vram_fops); debugfs_create_file("amdgpu_evict_gtt", 0400, root, adev, &amdgpu_evict_gtt_fops); debugfs_create_file("amdgpu_test_ib", 0400, root, adev, &amdgpu_debugfs_test_ib_fops); debugfs_create_file("amdgpu_vm_info", 0444, root, adev, &amdgpu_debugfs_vm_info_fops); debugfs_create_file("amdgpu_benchmark", 0200, root, adev, &amdgpu_benchmark_fops);
adev->debugfs_vbios_blob.data = adev->bios; adev->debugfs_vbios_blob.size = adev->bios_size; debugfs_create_blob("amdgpu_vbios", 0444, root, &adev->debugfs_vbios_blob);
if (adev->discovery.debugfs_blob.size) debugfs_create_blob("amdgpu_discovery", 0444, root, &adev->discovery.debugfs_blob);
return 0;}
static int amdgpu_pt_info_read(struct seq_file *m, void *unused){ struct drm_file *file; struct amdgpu_fpriv *fpriv; struct amdgpu_bo *root_bo; struct amdgpu_device *adev; int r;
file = m->private; if (!file) return -EINVAL;
adev = drm_to_adev(file->minor->dev); fpriv = file->driver_priv; if (!fpriv || !fpriv->vm.root.bo) return -ENODEV;
root_bo = amdgpu_bo_ref(fpriv->vm.root.bo); r = amdgpu_bo_reserve(root_bo, true); if (r) { amdgpu_bo_unref(&root_bo); return -EINVAL; }
seq_printf(m, "pd_address: 0x%llx\n", amdgpu_gmc_pd_addr(fpriv->vm.root.bo)); seq_printf(m, "max_pfn: 0x%llx\n", adev->vm_manager.max_pfn); seq_printf(m, "num_level: 0x%x\n", adev->vm_manager.num_level); seq_printf(m, "block_size: 0x%x\n", adev->vm_manager.block_size); seq_printf(m, "fragment_size: 0x%x\n", adev->vm_manager.fragment_size);
amdgpu_bo_unreserve(root_bo); amdgpu_bo_unref(&root_bo);
return 0;}
static int amdgpu_pt_info_open(struct inode *inode, struct file *file){ return single_open(file, amdgpu_pt_info_read, inode->i_private);}
static const struct file_operations amdgpu_pt_info_fops = { .owner = THIS_MODULE, .open = amdgpu_pt_info_open, .read = seq_read, .llseek = seq_lseek, .release = single_release,};
static int amdgpu_mqd_info_read(struct seq_file *m, void *unused){ struct amdgpu_usermode_queue *queue = m->private; struct amdgpu_bo *bo; int r;
if (!queue || !queue->mqd.obj) return -EINVAL;
bo = amdgpu_bo_ref(queue->mqd.obj); r = amdgpu_bo_reserve(bo, true); if (r) { amdgpu_bo_unref(&bo); return -EINVAL; }
seq_printf(m, "queue_type: %d\n", queue->queue_type); seq_printf(m, "mqd_gpu_address: 0x%llx\n", amdgpu_bo_gpu_offset(queue->mqd.obj));
amdgpu_bo_unreserve(bo); amdgpu_bo_unref(&bo);
return 0;}
static int amdgpu_mqd_info_open(struct inode *inode, struct file *file){ return single_open(file, amdgpu_mqd_info_read, inode->i_private);}
static const struct file_operations amdgpu_mqd_info_fops = { .owner = THIS_MODULE, .open = amdgpu_mqd_info_open, .read = seq_read, .llseek = seq_lseek, .release = single_release,};
void amdgpu_debugfs_userq_init(struct drm_file *file, struct amdgpu_usermode_queue *queue, int qid){ char queue_name[32];
scnprintf(queue_name, sizeof(queue_name), "queue_%d", qid); queue->debugfs_queue = debugfs_create_dir(queue_name, file->debugfs_client); debugfs_create_file("mqd_info", 0444, queue->debugfs_queue, queue, &amdgpu_mqd_info_fops);}
void amdgpu_debugfs_vm_init(struct drm_file *file){ debugfs_create_file("vm_pagetable_info", 0444, file->debugfs_client, file, &amdgpu_pt_info_fops);}
#elseint amdgpu_debugfs_init(struct amdgpu_device *adev){ return 0;}int amdgpu_debugfs_regs_init(struct amdgpu_device *adev){ return 0;}void amdgpu_debugfs_vm_init(struct drm_file *file){}void amdgpu_debugfs_userq_init(struct drm_file *file, struct amdgpu_usermode_queue *queue, int qid){}#endif