Path: blob/master/drivers/accel/habanalabs/common/debugfs.c
26436 views
// SPDX-License-Identifier: GPL-2.012/*3* Copyright 2016-2021 HabanaLabs, Ltd.4* All Rights Reserved.5*/67#include "habanalabs.h"8#include "../include/hw_ip/mmu/mmu_general.h"910#include <linux/pci.h>11#include <linux/uaccess.h>12#include <linux/vmalloc.h>13#include <linux/iommu.h>1415#define MMU_ADDR_BUF_SIZE 4016#define MMU_ASID_BUF_SIZE 1017#define MMU_KBUF_SIZE (MMU_ADDR_BUF_SIZE + MMU_ASID_BUF_SIZE)18#define I2C_MAX_TRANSACTION_LEN 81920static int hl_debugfs_i2c_read(struct hl_device *hdev, u8 i2c_bus, u8 i2c_addr,21u8 i2c_reg, u8 i2c_len, u64 *val)22{23struct cpucp_packet pkt;24int rc;2526if (!hl_device_operational(hdev, NULL))27return -EBUSY;2829if (i2c_len > I2C_MAX_TRANSACTION_LEN) {30dev_err(hdev->dev, "I2C transaction length %u, exceeds maximum of %u\n",31i2c_len, I2C_MAX_TRANSACTION_LEN);32return -EINVAL;33}3435memset(&pkt, 0, sizeof(pkt));3637pkt.ctl = cpu_to_le32(CPUCP_PACKET_I2C_RD <<38CPUCP_PKT_CTL_OPCODE_SHIFT);39pkt.i2c_bus = i2c_bus;40pkt.i2c_addr = i2c_addr;41pkt.i2c_reg = i2c_reg;42pkt.i2c_len = i2c_len;4344rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 0, val);45if (rc && rc != -EAGAIN)46dev_err(hdev->dev, "Failed to read from I2C, error %d\n", rc);4748return rc;49}5051static int hl_debugfs_i2c_write(struct hl_device *hdev, u8 i2c_bus, u8 i2c_addr,52u8 i2c_reg, u8 i2c_len, u64 val)53{54struct cpucp_packet pkt;55int rc;5657if (!hl_device_operational(hdev, NULL))58return -EBUSY;5960if (i2c_len > I2C_MAX_TRANSACTION_LEN) {61dev_err(hdev->dev, "I2C transaction length %u, exceeds maximum of %u\n",62i2c_len, I2C_MAX_TRANSACTION_LEN);63return -EINVAL;64}6566memset(&pkt, 0, sizeof(pkt));6768pkt.ctl = cpu_to_le32(CPUCP_PACKET_I2C_WR <<69CPUCP_PKT_CTL_OPCODE_SHIFT);70pkt.i2c_bus = i2c_bus;71pkt.i2c_addr = i2c_addr;72pkt.i2c_reg = i2c_reg;73pkt.i2c_len = i2c_len;74pkt.value = cpu_to_le64(val);7576rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 0, NULL);77if (rc && rc != -EAGAIN)78dev_err(hdev->dev, "Failed to write to I2C, error %d\n", rc);7980return rc;81}8283static void hl_debugfs_led_set(struct hl_device *hdev, u8 led, u8 state)84{85struct cpucp_packet pkt;86int rc;8788if (!hl_device_operational(hdev, NULL))89return;9091memset(&pkt, 0, sizeof(pkt));9293pkt.ctl = cpu_to_le32(CPUCP_PACKET_LED_SET <<94CPUCP_PKT_CTL_OPCODE_SHIFT);95pkt.led_index = cpu_to_le32(led);96pkt.value = cpu_to_le64(state);9798rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 0, NULL);99if (rc && rc != -EAGAIN)100dev_err(hdev->dev, "Failed to set LED %d, error %d\n", led, rc);101}102103static int command_buffers_show(struct seq_file *s, void *data)104{105struct hl_debugfs_entry *entry = s->private;106struct hl_dbg_device_entry *dev_entry = entry->dev_entry;107struct hl_cb *cb;108bool first = true;109110spin_lock(&dev_entry->cb_spinlock);111112list_for_each_entry(cb, &dev_entry->cb_list, debugfs_list) {113if (first) {114first = false;115seq_puts(s, "\n");116seq_puts(s, " CB ID CTX ID CB size CB RefCnt mmap? CS counter\n");117seq_puts(s, "---------------------------------------------------------------\n");118}119seq_printf(s,120" %03llu %d 0x%08x %d %d %d\n",121cb->buf->handle, cb->ctx->asid, cb->size,122kref_read(&cb->buf->refcount),123atomic_read(&cb->buf->mmap), atomic_read(&cb->cs_cnt));124}125126spin_unlock(&dev_entry->cb_spinlock);127128if (!first)129seq_puts(s, "\n");130131return 0;132}133134static int command_submission_show(struct seq_file *s, void *data)135{136struct hl_debugfs_entry *entry = s->private;137struct hl_dbg_device_entry *dev_entry = entry->dev_entry;138struct hl_cs *cs;139bool first = true;140141spin_lock(&dev_entry->cs_spinlock);142143list_for_each_entry(cs, &dev_entry->cs_list, debugfs_list) {144if (first) {145first = false;146seq_puts(s, "\n");147seq_puts(s, " CS ID CS TYPE CTX ASID CS RefCnt Submitted Completed\n");148seq_puts(s, "----------------------------------------------------------------\n");149}150seq_printf(s,151" %llu %d %d %d %d %d\n",152cs->sequence, cs->type, cs->ctx->asid,153kref_read(&cs->refcount),154cs->submitted, cs->completed);155}156157spin_unlock(&dev_entry->cs_spinlock);158159if (!first)160seq_puts(s, "\n");161162return 0;163}164165static int command_submission_jobs_show(struct seq_file *s, void *data)166{167struct hl_debugfs_entry *entry = s->private;168struct hl_dbg_device_entry *dev_entry = entry->dev_entry;169struct hl_cs_job *job;170bool first = true;171172spin_lock(&dev_entry->cs_job_spinlock);173174list_for_each_entry(job, &dev_entry->cs_job_list, debugfs_list) {175if (first) {176first = false;177seq_puts(s, "\n");178seq_puts(s, " JOB ID CS ID CS TYPE CTX ASID JOB RefCnt H/W Queue\n");179seq_puts(s, "---------------------------------------------------------------\n");180}181if (job->cs)182seq_printf(s,183" %02d %llu %d %d %d %d\n",184job->id, job->cs->sequence, job->cs->type,185job->cs->ctx->asid, kref_read(&job->refcount),186job->hw_queue_id);187else188seq_printf(s,189" %02d 0 0 %d %d %d\n",190job->id, HL_KERNEL_ASID_ID,191kref_read(&job->refcount), job->hw_queue_id);192}193194spin_unlock(&dev_entry->cs_job_spinlock);195196if (!first)197seq_puts(s, "\n");198199return 0;200}201202static int userptr_show(struct seq_file *s, void *data)203{204struct hl_debugfs_entry *entry = s->private;205struct hl_dbg_device_entry *dev_entry = entry->dev_entry;206struct hl_userptr *userptr;207char dma_dir[4][30] = {"DMA_BIDIRECTIONAL", "DMA_TO_DEVICE",208"DMA_FROM_DEVICE", "DMA_NONE"};209bool first = true;210211spin_lock(&dev_entry->userptr_spinlock);212213list_for_each_entry(userptr, &dev_entry->userptr_list, debugfs_list) {214if (first) {215first = false;216seq_puts(s, "\n");217seq_puts(s, " pid user virtual address size dma dir\n");218seq_puts(s, "----------------------------------------------------------\n");219}220seq_printf(s, " %-7d 0x%-14llx %-10llu %-30s\n",221userptr->pid, userptr->addr, userptr->size,222dma_dir[userptr->dir]);223}224225spin_unlock(&dev_entry->userptr_spinlock);226227if (!first)228seq_puts(s, "\n");229230return 0;231}232233static int vm_show(struct seq_file *s, void *data)234{235struct hl_debugfs_entry *entry = s->private;236struct hl_dbg_device_entry *dev_entry = entry->dev_entry;237struct hl_vm_hw_block_list_node *lnode;238struct hl_ctx *ctx;239struct hl_vm *vm;240struct hl_vm_hash_node *hnode;241struct hl_userptr *userptr;242struct hl_vm_phys_pg_pack *phys_pg_pack = NULL;243struct hl_va_range *va_range;244struct hl_vm_va_block *va_block;245enum vm_type *vm_type;246bool once = true;247u64 j;248int i;249250mutex_lock(&dev_entry->ctx_mem_hash_mutex);251252list_for_each_entry(ctx, &dev_entry->ctx_mem_hash_list, debugfs_list) {253once = false;254seq_puts(s, "\n\n----------------------------------------------------");255seq_puts(s, "\n----------------------------------------------------\n\n");256seq_printf(s, "ctx asid: %u\n", ctx->asid);257258seq_puts(s, "\nmappings:\n\n");259seq_puts(s, " virtual address size handle\n");260seq_puts(s, "----------------------------------------------------\n");261mutex_lock(&ctx->mem_hash_lock);262hash_for_each(ctx->mem_hash, i, hnode, node) {263vm_type = hnode->ptr;264265if (*vm_type == VM_TYPE_USERPTR) {266userptr = hnode->ptr;267seq_printf(s,268" 0x%-14llx %-10llu\n",269hnode->vaddr, userptr->size);270} else {271phys_pg_pack = hnode->ptr;272seq_printf(s,273" 0x%-14llx %-10llu %-4u\n",274hnode->vaddr, phys_pg_pack->total_size,275phys_pg_pack->handle);276}277}278mutex_unlock(&ctx->mem_hash_lock);279280if (ctx->asid != HL_KERNEL_ASID_ID &&281!list_empty(&ctx->hw_block_mem_list)) {282seq_puts(s, "\nhw_block mappings:\n\n");283seq_puts(s,284" virtual address block size mapped size HW block id\n");285seq_puts(s,286"---------------------------------------------------------------\n");287mutex_lock(&ctx->hw_block_list_lock);288list_for_each_entry(lnode, &ctx->hw_block_mem_list, node) {289seq_printf(s,290" 0x%-14lx %-6u %-6u %-9u\n",291lnode->vaddr, lnode->block_size, lnode->mapped_size,292lnode->id);293}294mutex_unlock(&ctx->hw_block_list_lock);295}296297vm = &ctx->hdev->vm;298spin_lock(&vm->idr_lock);299300if (!idr_is_empty(&vm->phys_pg_pack_handles))301seq_puts(s, "\n\nallocations:\n");302303idr_for_each_entry(&vm->phys_pg_pack_handles, phys_pg_pack, i) {304if (phys_pg_pack->asid != ctx->asid)305continue;306307seq_printf(s, "\nhandle: %u\n", phys_pg_pack->handle);308seq_printf(s, "page size: %u\n\n",309phys_pg_pack->page_size);310seq_puts(s, " physical address\n");311seq_puts(s, "---------------------\n");312for (j = 0 ; j < phys_pg_pack->npages ; j++) {313seq_printf(s, " 0x%-14llx\n",314phys_pg_pack->pages[j]);315}316}317spin_unlock(&vm->idr_lock);318319}320321mutex_unlock(&dev_entry->ctx_mem_hash_mutex);322323ctx = hl_get_compute_ctx(dev_entry->hdev);324if (ctx) {325seq_puts(s, "\nVA ranges:\n\n");326for (i = HL_VA_RANGE_TYPE_HOST ; i < HL_VA_RANGE_TYPE_MAX ; ++i) {327va_range = ctx->va_range[i];328seq_printf(s, " va_range %d\n", i);329seq_puts(s, "---------------------\n");330mutex_lock(&va_range->lock);331list_for_each_entry(va_block, &va_range->list, node) {332seq_printf(s, "%#16llx - %#16llx (%#llx)\n",333va_block->start, va_block->end,334va_block->size);335}336mutex_unlock(&va_range->lock);337seq_puts(s, "\n");338}339hl_ctx_put(ctx);340}341342if (!once)343seq_puts(s, "\n");344345return 0;346}347348static int userptr_lookup_show(struct seq_file *s, void *data)349{350struct hl_debugfs_entry *entry = s->private;351struct hl_dbg_device_entry *dev_entry = entry->dev_entry;352struct scatterlist *sg;353struct hl_userptr *userptr;354bool first = true;355u64 total_npages, npages, sg_start, sg_end;356dma_addr_t dma_addr;357int i;358359spin_lock(&dev_entry->userptr_spinlock);360361list_for_each_entry(userptr, &dev_entry->userptr_list, debugfs_list) {362if (dev_entry->userptr_lookup >= userptr->addr &&363dev_entry->userptr_lookup < userptr->addr + userptr->size) {364total_npages = 0;365for_each_sgtable_dma_sg(userptr->sgt, sg, i) {366npages = hl_get_sg_info(sg, &dma_addr);367sg_start = userptr->addr +368total_npages * PAGE_SIZE;369sg_end = userptr->addr +370(total_npages + npages) * PAGE_SIZE;371372if (dev_entry->userptr_lookup >= sg_start &&373dev_entry->userptr_lookup < sg_end) {374dma_addr += (dev_entry->userptr_lookup -375sg_start);376if (first) {377first = false;378seq_puts(s, "\n");379seq_puts(s, " user virtual address dma address pid region start region size\n");380seq_puts(s, "---------------------------------------------------------------------------------------\n");381}382seq_printf(s, " 0x%-18llx 0x%-16llx %-8u 0x%-16llx %-12llu\n",383dev_entry->userptr_lookup,384(u64)dma_addr, userptr->pid,385userptr->addr, userptr->size);386}387total_npages += npages;388}389}390}391392spin_unlock(&dev_entry->userptr_spinlock);393394if (!first)395seq_puts(s, "\n");396397return 0;398}399400static ssize_t userptr_lookup_write(struct file *file, const char __user *buf,401size_t count, loff_t *f_pos)402{403struct seq_file *s = file->private_data;404struct hl_debugfs_entry *entry = s->private;405struct hl_dbg_device_entry *dev_entry = entry->dev_entry;406ssize_t rc;407u64 value;408409rc = kstrtoull_from_user(buf, count, 16, &value);410if (rc)411return rc;412413dev_entry->userptr_lookup = value;414415return count;416}417418static int mmu_show(struct seq_file *s, void *data)419{420struct hl_debugfs_entry *entry = s->private;421struct hl_dbg_device_entry *dev_entry = entry->dev_entry;422struct hl_device *hdev = dev_entry->hdev;423struct hl_ctx *ctx;424struct hl_mmu_hop_info hops_info = {0};425u64 virt_addr = dev_entry->mmu_addr, phys_addr;426int i;427428if (dev_entry->mmu_asid == HL_KERNEL_ASID_ID)429ctx = hdev->kernel_ctx;430else431ctx = hl_get_compute_ctx(hdev);432433if (!ctx) {434dev_err(hdev->dev, "no ctx available\n");435return 0;436}437438if (hl_mmu_get_tlb_info(ctx, virt_addr, &hops_info)) {439dev_err(hdev->dev, "virt addr 0x%llx is not mapped to phys addr\n",440virt_addr);441goto put_ctx;442}443444hl_mmu_va_to_pa(ctx, virt_addr, &phys_addr);445446if (hops_info.scrambled_vaddr &&447(dev_entry->mmu_addr != hops_info.scrambled_vaddr))448seq_printf(s,449"asid: %u, virt_addr: 0x%llx, scrambled virt_addr: 0x%llx,\nphys_addr: 0x%llx, scrambled_phys_addr: 0x%llx\n",450dev_entry->mmu_asid, dev_entry->mmu_addr,451hops_info.scrambled_vaddr,452hops_info.unscrambled_paddr, phys_addr);453else454seq_printf(s,455"asid: %u, virt_addr: 0x%llx, phys_addr: 0x%llx\n",456dev_entry->mmu_asid, dev_entry->mmu_addr, phys_addr);457458for (i = 0 ; i < hops_info.used_hops ; i++) {459seq_printf(s, "hop%d_addr: 0x%llx\n",460i, hops_info.hop_info[i].hop_addr);461seq_printf(s, "hop%d_pte_addr: 0x%llx\n",462i, hops_info.hop_info[i].hop_pte_addr);463seq_printf(s, "hop%d_pte: 0x%llx\n",464i, hops_info.hop_info[i].hop_pte_val);465}466467put_ctx:468if (dev_entry->mmu_asid != HL_KERNEL_ASID_ID)469hl_ctx_put(ctx);470471return 0;472}473474static ssize_t mmu_asid_va_write(struct file *file, const char __user *buf,475size_t count, loff_t *f_pos)476{477struct seq_file *s = file->private_data;478struct hl_debugfs_entry *entry = s->private;479struct hl_dbg_device_entry *dev_entry = entry->dev_entry;480struct hl_device *hdev = dev_entry->hdev;481char kbuf[MMU_KBUF_SIZE] = {0};482char *c;483ssize_t rc;484485if (count > sizeof(kbuf) - 1)486goto err;487if (copy_from_user(kbuf, buf, count))488goto err;489kbuf[count] = 0;490491c = strchr(kbuf, ' ');492if (!c)493goto err;494*c = '\0';495496rc = kstrtouint(kbuf, 10, &dev_entry->mmu_asid);497if (rc)498goto err;499500if (strncmp(c+1, "0x", 2))501goto err;502rc = kstrtoull(c+3, 16, &dev_entry->mmu_addr);503if (rc)504goto err;505506return count;507508err:509dev_err(hdev->dev, "usage: echo <asid> <0xaddr> > mmu\n");510511return -EINVAL;512}513514static int mmu_ack_error(struct seq_file *s, void *data)515{516struct hl_debugfs_entry *entry = s->private;517struct hl_dbg_device_entry *dev_entry = entry->dev_entry;518struct hl_device *hdev = dev_entry->hdev;519int rc;520521if (!dev_entry->mmu_cap_mask) {522dev_err(hdev->dev, "mmu_cap_mask is not set\n");523goto err;524}525526rc = hdev->asic_funcs->ack_mmu_errors(hdev, dev_entry->mmu_cap_mask);527if (rc)528goto err;529530return 0;531err:532return -EINVAL;533}534535static ssize_t mmu_ack_error_value_write(struct file *file,536const char __user *buf,537size_t count, loff_t *f_pos)538{539struct seq_file *s = file->private_data;540struct hl_debugfs_entry *entry = s->private;541struct hl_dbg_device_entry *dev_entry = entry->dev_entry;542struct hl_device *hdev = dev_entry->hdev;543char kbuf[MMU_KBUF_SIZE] = {0};544ssize_t rc;545546if (count > sizeof(kbuf) - 1)547goto err;548549if (copy_from_user(kbuf, buf, count))550goto err;551552kbuf[count] = 0;553554if (strncmp(kbuf, "0x", 2))555goto err;556557rc = kstrtoull(kbuf, 16, &dev_entry->mmu_cap_mask);558if (rc)559goto err;560561return count;562err:563dev_err(hdev->dev, "usage: echo <0xmmu_cap_mask > > mmu_error\n");564565return -EINVAL;566}567568static int engines_show(struct seq_file *s, void *data)569{570struct hl_debugfs_entry *entry = s->private;571struct hl_dbg_device_entry *dev_entry = entry->dev_entry;572struct hl_device *hdev = dev_entry->hdev;573struct engines_data eng_data;574575if (hdev->reset_info.in_reset) {576dev_warn_ratelimited(hdev->dev,577"Can't check device idle during reset\n");578return 0;579}580581eng_data.actual_size = 0;582eng_data.allocated_buf_size = HL_ENGINES_DATA_MAX_SIZE;583eng_data.buf = vmalloc(eng_data.allocated_buf_size);584if (!eng_data.buf)585return -ENOMEM;586587hdev->asic_funcs->is_device_idle(hdev, NULL, 0, &eng_data);588589if (eng_data.actual_size > eng_data.allocated_buf_size) {590dev_err(hdev->dev,591"Engines data size (%d Bytes) is bigger than allocated size (%u Bytes)\n",592eng_data.actual_size, eng_data.allocated_buf_size);593vfree(eng_data.buf);594return -ENOMEM;595}596597seq_write(s, eng_data.buf, eng_data.actual_size);598599vfree(eng_data.buf);600601return 0;602}603604static ssize_t hl_memory_scrub(struct file *f, const char __user *buf,605size_t count, loff_t *ppos)606{607struct hl_dbg_device_entry *entry = file_inode(f)->i_private;608struct hl_device *hdev = entry->hdev;609u64 val = hdev->memory_scrub_val;610int rc;611612if (!hl_device_operational(hdev, NULL)) {613dev_warn_ratelimited(hdev->dev, "Can't scrub memory, device is not operational\n");614return -EIO;615}616617mutex_lock(&hdev->fpriv_list_lock);618if (hdev->is_compute_ctx_active) {619mutex_unlock(&hdev->fpriv_list_lock);620dev_err(hdev->dev, "can't scrub dram, context exist\n");621return -EBUSY;622}623hdev->is_in_dram_scrub = true;624mutex_unlock(&hdev->fpriv_list_lock);625626rc = hdev->asic_funcs->scrub_device_dram(hdev, val);627628mutex_lock(&hdev->fpriv_list_lock);629hdev->is_in_dram_scrub = false;630mutex_unlock(&hdev->fpriv_list_lock);631632if (rc)633return rc;634return count;635}636637static bool hl_is_device_va(struct hl_device *hdev, u64 addr)638{639struct asic_fixed_properties *prop = &hdev->asic_prop;640641if (prop->dram_supports_virtual_memory &&642(addr >= prop->dmmu.start_addr && addr < prop->dmmu.end_addr))643return true;644645if (addr >= prop->pmmu.start_addr &&646addr < prop->pmmu.end_addr)647return true;648649if (addr >= prop->pmmu_huge.start_addr &&650addr < prop->pmmu_huge.end_addr)651return true;652653return false;654}655656static bool hl_is_device_internal_memory_va(struct hl_device *hdev, u64 addr,657u32 size)658{659struct asic_fixed_properties *prop = &hdev->asic_prop;660u64 dram_start_addr, dram_end_addr;661662if (prop->dram_supports_virtual_memory) {663dram_start_addr = prop->dmmu.start_addr;664dram_end_addr = prop->dmmu.end_addr;665} else {666dram_start_addr = prop->dram_base_address;667dram_end_addr = prop->dram_end_address;668}669670if (hl_mem_area_inside_range(addr, size, dram_start_addr,671dram_end_addr))672return true;673674if (hl_mem_area_inside_range(addr, size, prop->sram_base_address,675prop->sram_end_address))676return true;677678return false;679}680681static int device_va_to_pa(struct hl_device *hdev, u64 virt_addr, u32 size,682u64 *phys_addr)683{684struct hl_vm_phys_pg_pack *phys_pg_pack;685struct hl_ctx *ctx;686struct hl_vm_hash_node *hnode;687u64 end_address, range_size;688struct hl_userptr *userptr;689enum vm_type *vm_type;690bool valid = false;691int i, rc = 0;692693ctx = hl_get_compute_ctx(hdev);694695if (!ctx) {696dev_err(hdev->dev, "no ctx available\n");697return -EINVAL;698}699700/* Verify address is mapped */701mutex_lock(&ctx->mem_hash_lock);702hash_for_each(ctx->mem_hash, i, hnode, node) {703vm_type = hnode->ptr;704705if (*vm_type == VM_TYPE_USERPTR) {706userptr = hnode->ptr;707range_size = userptr->size;708} else {709phys_pg_pack = hnode->ptr;710range_size = phys_pg_pack->total_size;711}712713end_address = virt_addr + size;714if ((virt_addr >= hnode->vaddr) &&715(end_address <= hnode->vaddr + range_size)) {716valid = true;717break;718}719}720mutex_unlock(&ctx->mem_hash_lock);721722if (!valid) {723dev_err(hdev->dev,724"virt addr 0x%llx is not mapped\n",725virt_addr);726rc = -EINVAL;727goto put_ctx;728}729730rc = hl_mmu_va_to_pa(ctx, virt_addr, phys_addr);731if (rc) {732dev_err(hdev->dev,733"virt addr 0x%llx is not mapped to phys addr\n",734virt_addr);735rc = -EINVAL;736}737738put_ctx:739hl_ctx_put(ctx);740741return rc;742}743744static int hl_access_dev_mem_by_region(struct hl_device *hdev, u64 addr,745u64 *val, enum debugfs_access_type acc_type, bool *found)746{747size_t acc_size = (acc_type == DEBUGFS_READ64 || acc_type == DEBUGFS_WRITE64) ?748sizeof(u64) : sizeof(u32);749struct pci_mem_region *mem_reg;750int i;751752for (i = 0; i < PCI_REGION_NUMBER; i++) {753mem_reg = &hdev->pci_mem_region[i];754if (!mem_reg->used)755continue;756if (addr >= mem_reg->region_base &&757addr <= mem_reg->region_base + mem_reg->region_size - acc_size) {758*found = true;759return hdev->asic_funcs->access_dev_mem(hdev, i, addr, val, acc_type);760}761}762return 0;763}764765static void hl_access_host_mem(struct hl_device *hdev, u64 addr, u64 *val,766enum debugfs_access_type acc_type)767{768struct asic_fixed_properties *prop = &hdev->asic_prop;769u64 offset = prop->device_dma_offset_for_host_access;770771switch (acc_type) {772case DEBUGFS_READ32:773*val = *(u32 *) phys_to_virt(addr - offset);774break;775case DEBUGFS_WRITE32:776*(u32 *) phys_to_virt(addr - offset) = *val;777break;778case DEBUGFS_READ64:779*val = *(u64 *) phys_to_virt(addr - offset);780break;781case DEBUGFS_WRITE64:782*(u64 *) phys_to_virt(addr - offset) = *val;783break;784default:785dev_err(hdev->dev, "hostmem access-type %d id not supported\n", acc_type);786break;787}788}789790static int hl_access_mem(struct hl_device *hdev, u64 addr, u64 *val,791enum debugfs_access_type acc_type)792{793size_t acc_size = (acc_type == DEBUGFS_READ64 || acc_type == DEBUGFS_WRITE64) ?794sizeof(u64) : sizeof(u32);795u64 host_start = hdev->asic_prop.host_base_address;796u64 host_end = hdev->asic_prop.host_end_address;797bool user_address, found = false;798int rc;799800user_address = hl_is_device_va(hdev, addr);801if (user_address) {802rc = device_va_to_pa(hdev, addr, acc_size, &addr);803if (rc)804return rc;805}806807rc = hl_access_dev_mem_by_region(hdev, addr, val, acc_type, &found);808if (rc) {809dev_err(hdev->dev,810"Failed reading addr %#llx from dev mem (%d)\n",811addr, rc);812return rc;813}814815if (found)816return 0;817818if (!user_address || device_iommu_mapped(&hdev->pdev->dev)) {819rc = -EINVAL;820goto err;821}822823if (addr >= host_start && addr <= host_end - acc_size) {824hl_access_host_mem(hdev, addr, val, acc_type);825} else {826rc = -EINVAL;827goto err;828}829830return 0;831err:832dev_err(hdev->dev, "invalid addr %#llx\n", addr);833return rc;834}835836static ssize_t hl_data_read32(struct file *f, char __user *buf,837size_t count, loff_t *ppos)838{839struct hl_dbg_device_entry *entry = file_inode(f)->i_private;840struct hl_device *hdev = entry->hdev;841u64 value64, addr = entry->addr;842char tmp_buf[32];843ssize_t rc;844u32 val;845846if (hdev->reset_info.in_reset) {847dev_warn_ratelimited(hdev->dev, "Can't read during reset\n");848return 0;849}850851if (*ppos)852return 0;853854rc = hl_access_mem(hdev, addr, &value64, DEBUGFS_READ32);855if (rc)856return rc;857858val = value64; /* downcast back to 32 */859860sprintf(tmp_buf, "0x%08x\n", val);861return simple_read_from_buffer(buf, count, ppos, tmp_buf,862strlen(tmp_buf));863}864865static ssize_t hl_data_write32(struct file *f, const char __user *buf,866size_t count, loff_t *ppos)867{868struct hl_dbg_device_entry *entry = file_inode(f)->i_private;869struct hl_device *hdev = entry->hdev;870u64 value64, addr = entry->addr;871u32 value;872ssize_t rc;873874if (hdev->reset_info.in_reset) {875dev_warn_ratelimited(hdev->dev, "Can't write during reset\n");876return 0;877}878879rc = kstrtouint_from_user(buf, count, 16, &value);880if (rc)881return rc;882883value64 = value;884rc = hl_access_mem(hdev, addr, &value64, DEBUGFS_WRITE32);885if (rc)886return rc;887888return count;889}890891static ssize_t hl_data_read64(struct file *f, char __user *buf,892size_t count, loff_t *ppos)893{894struct hl_dbg_device_entry *entry = file_inode(f)->i_private;895struct hl_device *hdev = entry->hdev;896u64 addr = entry->addr;897char tmp_buf[32];898ssize_t rc;899u64 val;900901if (hdev->reset_info.in_reset) {902dev_warn_ratelimited(hdev->dev, "Can't read during reset\n");903return 0;904}905906if (*ppos)907return 0;908909rc = hl_access_mem(hdev, addr, &val, DEBUGFS_READ64);910if (rc)911return rc;912913sprintf(tmp_buf, "0x%016llx\n", val);914return simple_read_from_buffer(buf, count, ppos, tmp_buf,915strlen(tmp_buf));916}917918static ssize_t hl_data_write64(struct file *f, const char __user *buf,919size_t count, loff_t *ppos)920{921struct hl_dbg_device_entry *entry = file_inode(f)->i_private;922struct hl_device *hdev = entry->hdev;923u64 addr = entry->addr;924u64 value;925ssize_t rc;926927if (hdev->reset_info.in_reset) {928dev_warn_ratelimited(hdev->dev, "Can't write during reset\n");929return 0;930}931932rc = kstrtoull_from_user(buf, count, 16, &value);933if (rc)934return rc;935936rc = hl_access_mem(hdev, addr, &value, DEBUGFS_WRITE64);937if (rc)938return rc;939940return count;941}942943static ssize_t hl_dma_size_write(struct file *f, const char __user *buf,944size_t count, loff_t *ppos)945{946struct hl_dbg_device_entry *entry = file_inode(f)->i_private;947struct hl_device *hdev = entry->hdev;948u64 addr = entry->addr;949ssize_t rc;950u32 size;951952if (hdev->reset_info.in_reset) {953dev_warn_ratelimited(hdev->dev, "Can't DMA during reset\n");954return 0;955}956rc = kstrtouint_from_user(buf, count, 16, &size);957if (rc)958return rc;959960if (!size) {961dev_err(hdev->dev, "DMA read failed. size can't be 0\n");962return -EINVAL;963}964965if (size > SZ_128M) {966dev_err(hdev->dev,967"DMA read failed. size can't be larger than 128MB\n");968return -EINVAL;969}970971if (!hl_is_device_internal_memory_va(hdev, addr, size)) {972dev_err(hdev->dev,973"DMA read failed. Invalid 0x%010llx + 0x%08x\n",974addr, size);975return -EINVAL;976}977978/* Free the previous allocation, if there was any */979entry->data_dma_blob_desc.size = 0;980vfree(entry->data_dma_blob_desc.data);981982entry->data_dma_blob_desc.data = vmalloc(size);983if (!entry->data_dma_blob_desc.data)984return -ENOMEM;985986rc = hdev->asic_funcs->debugfs_read_dma(hdev, addr, size,987entry->data_dma_blob_desc.data);988if (rc) {989dev_err(hdev->dev, "Failed to DMA from 0x%010llx\n", addr);990vfree(entry->data_dma_blob_desc.data);991entry->data_dma_blob_desc.data = NULL;992return -EIO;993}994995entry->data_dma_blob_desc.size = size;996997return count;998}9991000static ssize_t hl_monitor_dump_trigger(struct file *f, const char __user *buf,1001size_t count, loff_t *ppos)1002{1003struct hl_dbg_device_entry *entry = file_inode(f)->i_private;1004struct hl_device *hdev = entry->hdev;1005u32 size, trig;1006ssize_t rc;10071008if (hdev->reset_info.in_reset) {1009dev_warn_ratelimited(hdev->dev, "Can't dump monitors during reset\n");1010return 0;1011}1012rc = kstrtouint_from_user(buf, count, 10, &trig);1013if (rc)1014return rc;10151016if (trig != 1) {1017dev_err(hdev->dev, "Must write 1 to trigger monitor dump\n");1018return -EINVAL;1019}10201021size = sizeof(struct cpucp_monitor_dump);10221023/* Free the previous allocation, if there was any */1024entry->mon_dump_blob_desc.size = 0;1025vfree(entry->mon_dump_blob_desc.data);10261027entry->mon_dump_blob_desc.data = vmalloc(size);1028if (!entry->mon_dump_blob_desc.data)1029return -ENOMEM;10301031rc = hdev->asic_funcs->get_monitor_dump(hdev, entry->mon_dump_blob_desc.data);1032if (rc) {1033dev_err(hdev->dev, "Failed to dump monitors\n");1034vfree(entry->mon_dump_blob_desc.data);1035entry->mon_dump_blob_desc.data = NULL;1036return -EIO;1037}10381039entry->mon_dump_blob_desc.size = size;10401041return count;1042}10431044static ssize_t hl_get_power_state(struct file *f, char __user *buf,1045size_t count, loff_t *ppos)1046{1047struct hl_dbg_device_entry *entry = file_inode(f)->i_private;1048struct hl_device *hdev = entry->hdev;1049char tmp_buf[200];1050int i;10511052if (*ppos)1053return 0;10541055if (hdev->pdev->current_state == PCI_D0)1056i = 1;1057else if (hdev->pdev->current_state == PCI_D3hot)1058i = 2;1059else1060i = 3;10611062sprintf(tmp_buf,1063"current power state: %d\n1 - D0\n2 - D3hot\n3 - Unknown\n", i);1064return simple_read_from_buffer(buf, count, ppos, tmp_buf,1065strlen(tmp_buf));1066}10671068static ssize_t hl_set_power_state(struct file *f, const char __user *buf,1069size_t count, loff_t *ppos)1070{1071struct hl_dbg_device_entry *entry = file_inode(f)->i_private;1072struct hl_device *hdev = entry->hdev;1073u32 value;1074ssize_t rc;10751076rc = kstrtouint_from_user(buf, count, 10, &value);1077if (rc)1078return rc;10791080if (value == 1) {1081pci_set_power_state(hdev->pdev, PCI_D0);1082pci_restore_state(hdev->pdev);1083rc = pci_enable_device(hdev->pdev);1084if (rc < 0)1085return rc;1086} else if (value == 2) {1087pci_save_state(hdev->pdev);1088pci_disable_device(hdev->pdev);1089pci_set_power_state(hdev->pdev, PCI_D3hot);1090} else {1091dev_dbg(hdev->dev, "invalid power state value %u\n", value);1092return -EINVAL;1093}10941095return count;1096}10971098static ssize_t hl_i2c_data_read(struct file *f, char __user *buf,1099size_t count, loff_t *ppos)1100{1101struct hl_dbg_device_entry *entry = file_inode(f)->i_private;1102struct hl_device *hdev = entry->hdev;1103char tmp_buf[32];1104u64 val;1105ssize_t rc;11061107if (*ppos)1108return 0;11091110rc = hl_debugfs_i2c_read(hdev, entry->i2c_bus, entry->i2c_addr,1111entry->i2c_reg, entry->i2c_len, &val);1112if (rc) {1113dev_err(hdev->dev,1114"Failed to read from I2C bus %d, addr %d, reg %d, len %d\n",1115entry->i2c_bus, entry->i2c_addr, entry->i2c_reg, entry->i2c_len);1116return rc;1117}11181119sprintf(tmp_buf, "%#02llx\n", val);1120rc = simple_read_from_buffer(buf, count, ppos, tmp_buf,1121strlen(tmp_buf));11221123return rc;1124}11251126static ssize_t hl_i2c_data_write(struct file *f, const char __user *buf,1127size_t count, loff_t *ppos)1128{1129struct hl_dbg_device_entry *entry = file_inode(f)->i_private;1130struct hl_device *hdev = entry->hdev;1131u64 value;1132ssize_t rc;11331134rc = kstrtou64_from_user(buf, count, 16, &value);1135if (rc)1136return rc;11371138rc = hl_debugfs_i2c_write(hdev, entry->i2c_bus, entry->i2c_addr,1139entry->i2c_reg, entry->i2c_len, value);1140if (rc) {1141dev_err(hdev->dev,1142"Failed to write %#02llx to I2C bus %d, addr %d, reg %d, len %d\n",1143value, entry->i2c_bus, entry->i2c_addr, entry->i2c_reg, entry->i2c_len);1144return rc;1145}11461147return count;1148}11491150static ssize_t hl_led0_write(struct file *f, const char __user *buf,1151size_t count, loff_t *ppos)1152{1153struct hl_dbg_device_entry *entry = file_inode(f)->i_private;1154struct hl_device *hdev = entry->hdev;1155u32 value;1156ssize_t rc;11571158rc = kstrtouint_from_user(buf, count, 10, &value);1159if (rc)1160return rc;11611162value = value ? 1 : 0;11631164hl_debugfs_led_set(hdev, 0, value);11651166return count;1167}11681169static ssize_t hl_led1_write(struct file *f, const char __user *buf,1170size_t count, loff_t *ppos)1171{1172struct hl_dbg_device_entry *entry = file_inode(f)->i_private;1173struct hl_device *hdev = entry->hdev;1174u32 value;1175ssize_t rc;11761177rc = kstrtouint_from_user(buf, count, 10, &value);1178if (rc)1179return rc;11801181value = value ? 1 : 0;11821183hl_debugfs_led_set(hdev, 1, value);11841185return count;1186}11871188static ssize_t hl_led2_write(struct file *f, const char __user *buf,1189size_t count, loff_t *ppos)1190{1191struct hl_dbg_device_entry *entry = file_inode(f)->i_private;1192struct hl_device *hdev = entry->hdev;1193u32 value;1194ssize_t rc;11951196rc = kstrtouint_from_user(buf, count, 10, &value);1197if (rc)1198return rc;11991200value = value ? 1 : 0;12011202hl_debugfs_led_set(hdev, 2, value);12031204return count;1205}12061207static ssize_t hl_device_read(struct file *f, char __user *buf,1208size_t count, loff_t *ppos)1209{1210static const char *help =1211"Valid values: disable, enable, suspend, resume, cpu_timeout\n";1212return simple_read_from_buffer(buf, count, ppos, help, strlen(help));1213}12141215static ssize_t hl_device_write(struct file *f, const char __user *buf,1216size_t count, loff_t *ppos)1217{1218struct hl_dbg_device_entry *entry = file_inode(f)->i_private;1219struct hl_device *hdev = entry->hdev;1220char data[30] = {0};12211222/* don't allow partial writes */1223if (*ppos != 0)1224return 0;12251226simple_write_to_buffer(data, 29, ppos, buf, count);12271228if (strncmp("disable", data, strlen("disable")) == 0) {1229hdev->disabled = true;1230} else if (strncmp("enable", data, strlen("enable")) == 0) {1231hdev->disabled = false;1232} else if (strncmp("suspend", data, strlen("suspend")) == 0) {1233hdev->asic_funcs->suspend(hdev);1234} else if (strncmp("resume", data, strlen("resume")) == 0) {1235hdev->asic_funcs->resume(hdev);1236} else if (strncmp("cpu_timeout", data, strlen("cpu_timeout")) == 0) {1237hdev->device_cpu_disabled = true;1238} else {1239dev_err(hdev->dev,1240"Valid values: disable, enable, suspend, resume, cpu_timeout\n");1241count = -EINVAL;1242}12431244return count;1245}12461247static ssize_t hl_clk_gate_read(struct file *f, char __user *buf,1248size_t count, loff_t *ppos)1249{1250return 0;1251}12521253static ssize_t hl_clk_gate_write(struct file *f, const char __user *buf,1254size_t count, loff_t *ppos)1255{1256return count;1257}12581259static ssize_t hl_stop_on_err_read(struct file *f, char __user *buf,1260size_t count, loff_t *ppos)1261{1262struct hl_dbg_device_entry *entry = file_inode(f)->i_private;1263struct hl_device *hdev = entry->hdev;1264char tmp_buf[200];1265ssize_t rc;12661267if (!hdev->asic_prop.configurable_stop_on_err)1268return -EOPNOTSUPP;12691270if (*ppos)1271return 0;12721273sprintf(tmp_buf, "%d\n", hdev->stop_on_err);1274rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf,1275strlen(tmp_buf) + 1);12761277return rc;1278}12791280static ssize_t hl_stop_on_err_write(struct file *f, const char __user *buf,1281size_t count, loff_t *ppos)1282{1283struct hl_dbg_device_entry *entry = file_inode(f)->i_private;1284struct hl_device *hdev = entry->hdev;1285u32 value;1286ssize_t rc;12871288if (!hdev->asic_prop.configurable_stop_on_err)1289return -EOPNOTSUPP;12901291if (hdev->reset_info.in_reset) {1292dev_warn_ratelimited(hdev->dev,1293"Can't change stop on error during reset\n");1294return 0;1295}12961297rc = kstrtouint_from_user(buf, count, 10, &value);1298if (rc)1299return rc;13001301hdev->stop_on_err = value ? 1 : 0;13021303hl_device_reset(hdev, 0);13041305return count;1306}13071308static ssize_t hl_security_violations_read(struct file *f, char __user *buf,1309size_t count, loff_t *ppos)1310{1311struct hl_dbg_device_entry *entry = file_inode(f)->i_private;1312struct hl_device *hdev = entry->hdev;13131314hdev->asic_funcs->ack_protection_bits_errors(hdev);13151316return 0;1317}13181319static ssize_t hl_state_dump_read(struct file *f, char __user *buf,1320size_t count, loff_t *ppos)1321{1322struct hl_dbg_device_entry *entry = file_inode(f)->i_private;1323ssize_t rc;13241325down_read(&entry->state_dump_sem);1326if (!entry->state_dump[entry->state_dump_head])1327rc = 0;1328else1329rc = simple_read_from_buffer(1330buf, count, ppos,1331entry->state_dump[entry->state_dump_head],1332strlen(entry->state_dump[entry->state_dump_head]));1333up_read(&entry->state_dump_sem);13341335return rc;1336}13371338static ssize_t hl_state_dump_write(struct file *f, const char __user *buf,1339size_t count, loff_t *ppos)1340{1341struct hl_dbg_device_entry *entry = file_inode(f)->i_private;1342struct hl_device *hdev = entry->hdev;1343ssize_t rc;1344u32 size;1345int i;13461347rc = kstrtouint_from_user(buf, count, 10, &size);1348if (rc)1349return rc;13501351if (size <= 0 || size >= ARRAY_SIZE(entry->state_dump)) {1352dev_err(hdev->dev, "Invalid number of dumps to skip\n");1353return -EINVAL;1354}13551356if (entry->state_dump[entry->state_dump_head]) {1357down_write(&entry->state_dump_sem);1358for (i = 0; i < size; ++i) {1359vfree(entry->state_dump[entry->state_dump_head]);1360entry->state_dump[entry->state_dump_head] = NULL;1361if (entry->state_dump_head > 0)1362entry->state_dump_head--;1363else1364entry->state_dump_head =1365ARRAY_SIZE(entry->state_dump) - 1;1366}1367up_write(&entry->state_dump_sem);1368}13691370return count;1371}13721373static ssize_t hl_timeout_locked_read(struct file *f, char __user *buf,1374size_t count, loff_t *ppos)1375{1376struct hl_dbg_device_entry *entry = file_inode(f)->i_private;1377struct hl_device *hdev = entry->hdev;1378char tmp_buf[200];1379ssize_t rc;13801381if (*ppos)1382return 0;13831384sprintf(tmp_buf, "%d\n",1385jiffies_to_msecs(hdev->timeout_jiffies) / 1000);1386rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf,1387strlen(tmp_buf) + 1);13881389return rc;1390}13911392static ssize_t hl_timeout_locked_write(struct file *f, const char __user *buf,1393size_t count, loff_t *ppos)1394{1395struct hl_dbg_device_entry *entry = file_inode(f)->i_private;1396struct hl_device *hdev = entry->hdev;1397u32 value;1398ssize_t rc;13991400rc = kstrtouint_from_user(buf, count, 10, &value);1401if (rc)1402return rc;14031404if (value)1405hdev->timeout_jiffies = secs_to_jiffies(value);1406else1407hdev->timeout_jiffies = MAX_SCHEDULE_TIMEOUT;14081409return count;1410}14111412static ssize_t hl_check_razwi_happened(struct file *f, char __user *buf,1413size_t count, loff_t *ppos)1414{1415struct hl_dbg_device_entry *entry = file_inode(f)->i_private;1416struct hl_device *hdev = entry->hdev;14171418hdev->asic_funcs->check_if_razwi_happened(hdev);14191420return 0;1421}14221423static const struct file_operations hl_mem_scrub_fops = {1424.owner = THIS_MODULE,1425.write = hl_memory_scrub,1426};14271428static const struct file_operations hl_data32b_fops = {1429.owner = THIS_MODULE,1430.read = hl_data_read32,1431.write = hl_data_write321432};14331434static const struct file_operations hl_data64b_fops = {1435.owner = THIS_MODULE,1436.read = hl_data_read64,1437.write = hl_data_write641438};14391440static const struct file_operations hl_dma_size_fops = {1441.owner = THIS_MODULE,1442.write = hl_dma_size_write1443};14441445static const struct file_operations hl_monitor_dump_fops = {1446.owner = THIS_MODULE,1447.write = hl_monitor_dump_trigger1448};14491450static const struct file_operations hl_i2c_data_fops = {1451.owner = THIS_MODULE,1452.read = hl_i2c_data_read,1453.write = hl_i2c_data_write1454};14551456static const struct file_operations hl_power_fops = {1457.owner = THIS_MODULE,1458.read = hl_get_power_state,1459.write = hl_set_power_state1460};14611462static const struct file_operations hl_led0_fops = {1463.owner = THIS_MODULE,1464.write = hl_led0_write1465};14661467static const struct file_operations hl_led1_fops = {1468.owner = THIS_MODULE,1469.write = hl_led1_write1470};14711472static const struct file_operations hl_led2_fops = {1473.owner = THIS_MODULE,1474.write = hl_led2_write1475};14761477static const struct file_operations hl_device_fops = {1478.owner = THIS_MODULE,1479.read = hl_device_read,1480.write = hl_device_write1481};14821483static const struct file_operations hl_clk_gate_fops = {1484.owner = THIS_MODULE,1485.read = hl_clk_gate_read,1486.write = hl_clk_gate_write1487};14881489static const struct file_operations hl_stop_on_err_fops = {1490.owner = THIS_MODULE,1491.read = hl_stop_on_err_read,1492.write = hl_stop_on_err_write1493};14941495static const struct file_operations hl_security_violations_fops = {1496.owner = THIS_MODULE,1497.read = hl_security_violations_read1498};14991500static const struct file_operations hl_state_dump_fops = {1501.owner = THIS_MODULE,1502.read = hl_state_dump_read,1503.write = hl_state_dump_write1504};15051506static const struct file_operations hl_timeout_locked_fops = {1507.owner = THIS_MODULE,1508.read = hl_timeout_locked_read,1509.write = hl_timeout_locked_write1510};15111512static const struct file_operations hl_razwi_check_fops = {1513.owner = THIS_MODULE,1514.read = hl_check_razwi_happened1515};15161517static const struct hl_info_list hl_debugfs_list[] = {1518{"command_buffers", command_buffers_show, NULL},1519{"command_submission", command_submission_show, NULL},1520{"command_submission_jobs", command_submission_jobs_show, NULL},1521{"userptr", userptr_show, NULL},1522{"vm", vm_show, NULL},1523{"userptr_lookup", userptr_lookup_show, userptr_lookup_write},1524{"mmu", mmu_show, mmu_asid_va_write},1525{"mmu_error", mmu_ack_error, mmu_ack_error_value_write},1526{"engines", engines_show, NULL},1527};15281529static int hl_debugfs_open(struct inode *inode, struct file *file)1530{1531struct hl_debugfs_entry *node = inode->i_private;15321533return single_open(file, node->info_ent->show, node);1534}15351536static ssize_t hl_debugfs_write(struct file *file, const char __user *buf,1537size_t count, loff_t *f_pos)1538{1539struct hl_debugfs_entry *node = file->f_inode->i_private;15401541if (node->info_ent->write)1542return node->info_ent->write(file, buf, count, f_pos);1543else1544return -EINVAL;15451546}15471548static const struct file_operations hl_debugfs_fops = {1549.owner = THIS_MODULE,1550.open = hl_debugfs_open,1551.read = seq_read,1552.write = hl_debugfs_write,1553.llseek = seq_lseek,1554.release = single_release,1555};15561557static void add_secured_nodes(struct hl_dbg_device_entry *dev_entry, struct dentry *root)1558{1559debugfs_create_u8("i2c_bus",15600644,1561root,1562&dev_entry->i2c_bus);15631564debugfs_create_u8("i2c_addr",15650644,1566root,1567&dev_entry->i2c_addr);15681569debugfs_create_u8("i2c_reg",15700644,1571root,1572&dev_entry->i2c_reg);15731574debugfs_create_u8("i2c_len",15750644,1576root,1577&dev_entry->i2c_len);15781579debugfs_create_file("i2c_data",15800644,1581root,1582dev_entry,1583&hl_i2c_data_fops);15841585debugfs_create_file("led0",15860200,1587root,1588dev_entry,1589&hl_led0_fops);15901591debugfs_create_file("led1",15920200,1593root,1594dev_entry,1595&hl_led1_fops);15961597debugfs_create_file("led2",15980200,1599root,1600dev_entry,1601&hl_led2_fops);1602}16031604static void add_files_to_device(struct hl_device *hdev, struct hl_dbg_device_entry *dev_entry,1605struct dentry *root)1606{1607int count = ARRAY_SIZE(hl_debugfs_list);1608struct hl_debugfs_entry *entry;1609int i;16101611debugfs_create_x64("memory_scrub_val",16120644,1613root,1614&hdev->memory_scrub_val);16151616debugfs_create_file("memory_scrub",16170200,1618root,1619dev_entry,1620&hl_mem_scrub_fops);16211622debugfs_create_x64("addr",16230644,1624root,1625&dev_entry->addr);16261627debugfs_create_file("data32",16280644,1629root,1630dev_entry,1631&hl_data32b_fops);16321633debugfs_create_file("data64",16340644,1635root,1636dev_entry,1637&hl_data64b_fops);16381639debugfs_create_file("set_power_state",16400644,1641root,1642dev_entry,1643&hl_power_fops);16441645debugfs_create_file("device",16460644,1647root,1648dev_entry,1649&hl_device_fops);16501651debugfs_create_file("clk_gate",16520644,1653root,1654dev_entry,1655&hl_clk_gate_fops);16561657debugfs_create_file("stop_on_err",16580644,1659root,1660dev_entry,1661&hl_stop_on_err_fops);16621663debugfs_create_file("dump_security_violations",16640400,1665root,1666dev_entry,1667&hl_security_violations_fops);16681669debugfs_create_file("dump_razwi_events",16700400,1671root,1672dev_entry,1673&hl_razwi_check_fops);16741675debugfs_create_file("dma_size",16760200,1677root,1678dev_entry,1679&hl_dma_size_fops);16801681debugfs_create_blob("data_dma",16820400,1683root,1684&dev_entry->data_dma_blob_desc);16851686debugfs_create_file("monitor_dump_trig",16870200,1688root,1689dev_entry,1690&hl_monitor_dump_fops);16911692debugfs_create_blob("monitor_dump",16930400,1694root,1695&dev_entry->mon_dump_blob_desc);16961697debugfs_create_x8("skip_reset_on_timeout",16980644,1699root,1700&hdev->reset_info.skip_reset_on_timeout);17011702debugfs_create_file("state_dump",17030644,1704root,1705dev_entry,1706&hl_state_dump_fops);17071708debugfs_create_file("timeout_locked",17090644,1710root,1711dev_entry,1712&hl_timeout_locked_fops);17131714debugfs_create_u32("device_release_watchdog_timeout",17150644,1716root,1717&hdev->device_release_watchdog_timeout_sec);17181719debugfs_create_u16("server_type",17200444,1721root,1722&hdev->asic_prop.server_type);17231724for (i = 0, entry = dev_entry->entry_arr ; i < count ; i++, entry++) {1725debugfs_create_file(hl_debugfs_list[i].name,17260644,1727root,1728entry,1729&hl_debugfs_fops);1730entry->info_ent = &hl_debugfs_list[i];1731entry->dev_entry = dev_entry;1732}1733}17341735int hl_debugfs_device_init(struct hl_device *hdev)1736{1737struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;1738int count = ARRAY_SIZE(hl_debugfs_list);17391740dev_entry->hdev = hdev;1741dev_entry->entry_arr = kmalloc_array(count, sizeof(struct hl_debugfs_entry), GFP_KERNEL);1742if (!dev_entry->entry_arr)1743return -ENOMEM;17441745dev_entry->data_dma_blob_desc.size = 0;1746dev_entry->data_dma_blob_desc.data = NULL;1747dev_entry->mon_dump_blob_desc.size = 0;1748dev_entry->mon_dump_blob_desc.data = NULL;17491750INIT_LIST_HEAD(&dev_entry->file_list);1751INIT_LIST_HEAD(&dev_entry->cb_list);1752INIT_LIST_HEAD(&dev_entry->cs_list);1753INIT_LIST_HEAD(&dev_entry->cs_job_list);1754INIT_LIST_HEAD(&dev_entry->userptr_list);1755INIT_LIST_HEAD(&dev_entry->ctx_mem_hash_list);1756mutex_init(&dev_entry->file_mutex);1757init_rwsem(&dev_entry->state_dump_sem);1758spin_lock_init(&dev_entry->cb_spinlock);1759spin_lock_init(&dev_entry->cs_spinlock);1760spin_lock_init(&dev_entry->cs_job_spinlock);1761spin_lock_init(&dev_entry->userptr_spinlock);1762mutex_init(&dev_entry->ctx_mem_hash_mutex);17631764return 0;1765}17661767void hl_debugfs_device_fini(struct hl_device *hdev)1768{1769struct hl_dbg_device_entry *entry = &hdev->hl_debugfs;1770int i;17711772mutex_destroy(&entry->ctx_mem_hash_mutex);1773mutex_destroy(&entry->file_mutex);17741775vfree(entry->data_dma_blob_desc.data);1776vfree(entry->mon_dump_blob_desc.data);17771778for (i = 0; i < ARRAY_SIZE(entry->state_dump); ++i)1779vfree(entry->state_dump[i]);17801781kfree(entry->entry_arr);1782}17831784void hl_debugfs_add_device(struct hl_device *hdev)1785{1786struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;17871788dev_entry->root = hdev->drm.accel->debugfs_root;17891790add_files_to_device(hdev, dev_entry, dev_entry->root);17911792if (!hdev->asic_prop.fw_security_enabled)1793add_secured_nodes(dev_entry, dev_entry->root);1794}17951796void hl_debugfs_add_file(struct hl_fpriv *hpriv)1797{1798struct hl_dbg_device_entry *dev_entry = &hpriv->hdev->hl_debugfs;17991800mutex_lock(&dev_entry->file_mutex);1801list_add(&hpriv->debugfs_list, &dev_entry->file_list);1802mutex_unlock(&dev_entry->file_mutex);1803}18041805void hl_debugfs_remove_file(struct hl_fpriv *hpriv)1806{1807struct hl_dbg_device_entry *dev_entry = &hpriv->hdev->hl_debugfs;18081809mutex_lock(&dev_entry->file_mutex);1810list_del(&hpriv->debugfs_list);1811mutex_unlock(&dev_entry->file_mutex);1812}18131814void hl_debugfs_add_cb(struct hl_cb *cb)1815{1816struct hl_dbg_device_entry *dev_entry = &cb->hdev->hl_debugfs;18171818spin_lock(&dev_entry->cb_spinlock);1819list_add(&cb->debugfs_list, &dev_entry->cb_list);1820spin_unlock(&dev_entry->cb_spinlock);1821}18221823void hl_debugfs_remove_cb(struct hl_cb *cb)1824{1825struct hl_dbg_device_entry *dev_entry = &cb->hdev->hl_debugfs;18261827spin_lock(&dev_entry->cb_spinlock);1828list_del(&cb->debugfs_list);1829spin_unlock(&dev_entry->cb_spinlock);1830}18311832void hl_debugfs_add_cs(struct hl_cs *cs)1833{1834struct hl_dbg_device_entry *dev_entry = &cs->ctx->hdev->hl_debugfs;18351836spin_lock(&dev_entry->cs_spinlock);1837list_add(&cs->debugfs_list, &dev_entry->cs_list);1838spin_unlock(&dev_entry->cs_spinlock);1839}18401841void hl_debugfs_remove_cs(struct hl_cs *cs)1842{1843struct hl_dbg_device_entry *dev_entry = &cs->ctx->hdev->hl_debugfs;18441845spin_lock(&dev_entry->cs_spinlock);1846list_del(&cs->debugfs_list);1847spin_unlock(&dev_entry->cs_spinlock);1848}18491850void hl_debugfs_add_job(struct hl_device *hdev, struct hl_cs_job *job)1851{1852struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;18531854spin_lock(&dev_entry->cs_job_spinlock);1855list_add(&job->debugfs_list, &dev_entry->cs_job_list);1856spin_unlock(&dev_entry->cs_job_spinlock);1857}18581859void hl_debugfs_remove_job(struct hl_device *hdev, struct hl_cs_job *job)1860{1861struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;18621863spin_lock(&dev_entry->cs_job_spinlock);1864list_del(&job->debugfs_list);1865spin_unlock(&dev_entry->cs_job_spinlock);1866}18671868void hl_debugfs_add_userptr(struct hl_device *hdev, struct hl_userptr *userptr)1869{1870struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;18711872spin_lock(&dev_entry->userptr_spinlock);1873list_add(&userptr->debugfs_list, &dev_entry->userptr_list);1874spin_unlock(&dev_entry->userptr_spinlock);1875}18761877void hl_debugfs_remove_userptr(struct hl_device *hdev,1878struct hl_userptr *userptr)1879{1880struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;18811882spin_lock(&dev_entry->userptr_spinlock);1883list_del(&userptr->debugfs_list);1884spin_unlock(&dev_entry->userptr_spinlock);1885}18861887void hl_debugfs_add_ctx_mem_hash(struct hl_device *hdev, struct hl_ctx *ctx)1888{1889struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;18901891mutex_lock(&dev_entry->ctx_mem_hash_mutex);1892list_add(&ctx->debugfs_list, &dev_entry->ctx_mem_hash_list);1893mutex_unlock(&dev_entry->ctx_mem_hash_mutex);1894}18951896void hl_debugfs_remove_ctx_mem_hash(struct hl_device *hdev, struct hl_ctx *ctx)1897{1898struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;18991900mutex_lock(&dev_entry->ctx_mem_hash_mutex);1901list_del(&ctx->debugfs_list);1902mutex_unlock(&dev_entry->ctx_mem_hash_mutex);1903}19041905/**1906* hl_debugfs_set_state_dump - register state dump making it accessible via1907* debugfs1908* @hdev: pointer to the device structure1909* @data: the actual dump data1910* @length: the length of the data1911*/1912void hl_debugfs_set_state_dump(struct hl_device *hdev, char *data,1913unsigned long length)1914{1915struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;19161917down_write(&dev_entry->state_dump_sem);19181919dev_entry->state_dump_head = (dev_entry->state_dump_head + 1) %1920ARRAY_SIZE(dev_entry->state_dump);1921vfree(dev_entry->state_dump[dev_entry->state_dump_head]);1922dev_entry->state_dump[dev_entry->state_dump_head] = data;19231924up_write(&dev_entry->state_dump_sem);1925}192619271928