162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci/* 462306a36Sopenharmony_ci * Copyright 2016-2021 HabanaLabs, Ltd. 562306a36Sopenharmony_ci * All Rights Reserved. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "habanalabs.h" 962306a36Sopenharmony_ci#include "../include/hw_ip/mmu/mmu_general.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/pci.h> 1262306a36Sopenharmony_ci#include <linux/uaccess.h> 1362306a36Sopenharmony_ci#include <linux/vmalloc.h> 1462306a36Sopenharmony_ci#include <linux/iommu.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define MMU_ADDR_BUF_SIZE 40 1762306a36Sopenharmony_ci#define MMU_ASID_BUF_SIZE 10 1862306a36Sopenharmony_ci#define MMU_KBUF_SIZE (MMU_ADDR_BUF_SIZE + MMU_ASID_BUF_SIZE) 1962306a36Sopenharmony_ci#define I2C_MAX_TRANSACTION_LEN 8 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistatic struct dentry *hl_debug_root; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic int hl_debugfs_i2c_read(struct hl_device *hdev, u8 i2c_bus, u8 i2c_addr, 2462306a36Sopenharmony_ci u8 i2c_reg, u8 i2c_len, u64 *val) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci struct cpucp_packet pkt; 2762306a36Sopenharmony_ci int rc; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci if (!hl_device_operational(hdev, NULL)) 3062306a36Sopenharmony_ci return -EBUSY; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci if (i2c_len > I2C_MAX_TRANSACTION_LEN) { 3362306a36Sopenharmony_ci dev_err(hdev->dev, "I2C transaction length %u, exceeds maximum of %u\n", 3462306a36Sopenharmony_ci i2c_len, I2C_MAX_TRANSACTION_LEN); 3562306a36Sopenharmony_ci return -EINVAL; 3662306a36Sopenharmony_ci } 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci memset(&pkt, 0, sizeof(pkt)); 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci pkt.ctl = cpu_to_le32(CPUCP_PACKET_I2C_RD << 4162306a36Sopenharmony_ci CPUCP_PKT_CTL_OPCODE_SHIFT); 4262306a36Sopenharmony_ci pkt.i2c_bus = i2c_bus; 4362306a36Sopenharmony_ci pkt.i2c_addr = i2c_addr; 4462306a36Sopenharmony_ci pkt.i2c_reg = i2c_reg; 4562306a36Sopenharmony_ci pkt.i2c_len = i2c_len; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 4862306a36Sopenharmony_ci 0, val); 4962306a36Sopenharmony_ci if (rc) 5062306a36Sopenharmony_ci dev_err(hdev->dev, "Failed to read from I2C, error %d\n", rc); 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci return rc; 5362306a36Sopenharmony_ci} 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistatic int hl_debugfs_i2c_write(struct hl_device *hdev, u8 i2c_bus, u8 i2c_addr, 5662306a36Sopenharmony_ci u8 i2c_reg, u8 i2c_len, u64 val) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci struct cpucp_packet pkt; 5962306a36Sopenharmony_ci int rc; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci if (!hl_device_operational(hdev, NULL)) 6262306a36Sopenharmony_ci return -EBUSY; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci if (i2c_len > I2C_MAX_TRANSACTION_LEN) { 6562306a36Sopenharmony_ci dev_err(hdev->dev, "I2C transaction length %u, exceeds maximum of %u\n", 6662306a36Sopenharmony_ci i2c_len, I2C_MAX_TRANSACTION_LEN); 6762306a36Sopenharmony_ci return -EINVAL; 6862306a36Sopenharmony_ci } 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci memset(&pkt, 0, sizeof(pkt)); 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci pkt.ctl = cpu_to_le32(CPUCP_PACKET_I2C_WR << 7362306a36Sopenharmony_ci CPUCP_PKT_CTL_OPCODE_SHIFT); 7462306a36Sopenharmony_ci pkt.i2c_bus = i2c_bus; 7562306a36Sopenharmony_ci pkt.i2c_addr = i2c_addr; 7662306a36Sopenharmony_ci pkt.i2c_reg = i2c_reg; 7762306a36Sopenharmony_ci pkt.i2c_len = i2c_len; 7862306a36Sopenharmony_ci pkt.value = cpu_to_le64(val); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 8162306a36Sopenharmony_ci 0, NULL); 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci if (rc) 8462306a36Sopenharmony_ci dev_err(hdev->dev, "Failed to write to I2C, error %d\n", rc); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci return rc; 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic void hl_debugfs_led_set(struct hl_device *hdev, u8 led, u8 state) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci struct cpucp_packet pkt; 9262306a36Sopenharmony_ci int rc; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci if (!hl_device_operational(hdev, NULL)) 9562306a36Sopenharmony_ci return; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci memset(&pkt, 0, sizeof(pkt)); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci pkt.ctl = cpu_to_le32(CPUCP_PACKET_LED_SET << 10062306a36Sopenharmony_ci CPUCP_PKT_CTL_OPCODE_SHIFT); 10162306a36Sopenharmony_ci pkt.led_index = cpu_to_le32(led); 10262306a36Sopenharmony_ci pkt.value = cpu_to_le64(state); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 10562306a36Sopenharmony_ci 0, NULL); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci if (rc) 10862306a36Sopenharmony_ci dev_err(hdev->dev, "Failed to set LED %d, error %d\n", led, rc); 10962306a36Sopenharmony_ci} 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cistatic int command_buffers_show(struct seq_file *s, void *data) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci struct hl_debugfs_entry *entry = s->private; 11462306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = entry->dev_entry; 11562306a36Sopenharmony_ci struct hl_cb *cb; 11662306a36Sopenharmony_ci bool first = true; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci spin_lock(&dev_entry->cb_spinlock); 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci list_for_each_entry(cb, &dev_entry->cb_list, debugfs_list) { 12162306a36Sopenharmony_ci if (first) { 12262306a36Sopenharmony_ci first = false; 12362306a36Sopenharmony_ci seq_puts(s, "\n"); 12462306a36Sopenharmony_ci seq_puts(s, " CB ID CTX ID CB size CB RefCnt mmap? CS counter\n"); 12562306a36Sopenharmony_ci seq_puts(s, "---------------------------------------------------------------\n"); 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci seq_printf(s, 12862306a36Sopenharmony_ci " %03llu %d 0x%08x %d %d %d\n", 12962306a36Sopenharmony_ci cb->buf->handle, cb->ctx->asid, cb->size, 13062306a36Sopenharmony_ci kref_read(&cb->buf->refcount), 13162306a36Sopenharmony_ci atomic_read(&cb->buf->mmap), atomic_read(&cb->cs_cnt)); 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci spin_unlock(&dev_entry->cb_spinlock); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci if (!first) 13762306a36Sopenharmony_ci seq_puts(s, "\n"); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci return 0; 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic int command_submission_show(struct seq_file *s, void *data) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci struct hl_debugfs_entry *entry = s->private; 14562306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = entry->dev_entry; 14662306a36Sopenharmony_ci struct hl_cs *cs; 14762306a36Sopenharmony_ci bool first = true; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci spin_lock(&dev_entry->cs_spinlock); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci list_for_each_entry(cs, &dev_entry->cs_list, debugfs_list) { 15262306a36Sopenharmony_ci if (first) { 15362306a36Sopenharmony_ci first = false; 15462306a36Sopenharmony_ci seq_puts(s, "\n"); 15562306a36Sopenharmony_ci seq_puts(s, " CS ID CS TYPE CTX ASID CS RefCnt Submitted Completed\n"); 15662306a36Sopenharmony_ci seq_puts(s, "----------------------------------------------------------------\n"); 15762306a36Sopenharmony_ci } 15862306a36Sopenharmony_ci seq_printf(s, 15962306a36Sopenharmony_ci " %llu %d %d %d %d %d\n", 16062306a36Sopenharmony_ci cs->sequence, cs->type, cs->ctx->asid, 16162306a36Sopenharmony_ci kref_read(&cs->refcount), 16262306a36Sopenharmony_ci cs->submitted, cs->completed); 16362306a36Sopenharmony_ci } 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci spin_unlock(&dev_entry->cs_spinlock); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci if (!first) 16862306a36Sopenharmony_ci seq_puts(s, "\n"); 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci return 0; 17162306a36Sopenharmony_ci} 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_cistatic int command_submission_jobs_show(struct seq_file *s, void *data) 17462306a36Sopenharmony_ci{ 17562306a36Sopenharmony_ci struct hl_debugfs_entry *entry = s->private; 17662306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = entry->dev_entry; 17762306a36Sopenharmony_ci struct hl_cs_job *job; 17862306a36Sopenharmony_ci bool first = true; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci spin_lock(&dev_entry->cs_job_spinlock); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci list_for_each_entry(job, &dev_entry->cs_job_list, debugfs_list) { 18362306a36Sopenharmony_ci if (first) { 18462306a36Sopenharmony_ci first = false; 18562306a36Sopenharmony_ci seq_puts(s, "\n"); 18662306a36Sopenharmony_ci seq_puts(s, " JOB ID CS ID CS TYPE CTX ASID JOB RefCnt H/W Queue\n"); 18762306a36Sopenharmony_ci seq_puts(s, "---------------------------------------------------------------\n"); 18862306a36Sopenharmony_ci } 18962306a36Sopenharmony_ci if (job->cs) 19062306a36Sopenharmony_ci seq_printf(s, 19162306a36Sopenharmony_ci " %02d %llu %d %d %d %d\n", 19262306a36Sopenharmony_ci job->id, job->cs->sequence, job->cs->type, 19362306a36Sopenharmony_ci job->cs->ctx->asid, kref_read(&job->refcount), 19462306a36Sopenharmony_ci job->hw_queue_id); 19562306a36Sopenharmony_ci else 19662306a36Sopenharmony_ci seq_printf(s, 19762306a36Sopenharmony_ci " %02d 0 0 %d %d %d\n", 19862306a36Sopenharmony_ci job->id, HL_KERNEL_ASID_ID, 19962306a36Sopenharmony_ci kref_read(&job->refcount), job->hw_queue_id); 20062306a36Sopenharmony_ci } 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci spin_unlock(&dev_entry->cs_job_spinlock); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci if (!first) 20562306a36Sopenharmony_ci seq_puts(s, "\n"); 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci return 0; 20862306a36Sopenharmony_ci} 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_cistatic int userptr_show(struct seq_file *s, void *data) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci struct hl_debugfs_entry *entry = s->private; 21362306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = entry->dev_entry; 21462306a36Sopenharmony_ci struct hl_userptr *userptr; 21562306a36Sopenharmony_ci char dma_dir[4][30] = {"DMA_BIDIRECTIONAL", "DMA_TO_DEVICE", 21662306a36Sopenharmony_ci "DMA_FROM_DEVICE", "DMA_NONE"}; 21762306a36Sopenharmony_ci bool first = true; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci spin_lock(&dev_entry->userptr_spinlock); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci list_for_each_entry(userptr, &dev_entry->userptr_list, debugfs_list) { 22262306a36Sopenharmony_ci if (first) { 22362306a36Sopenharmony_ci first = false; 22462306a36Sopenharmony_ci seq_puts(s, "\n"); 22562306a36Sopenharmony_ci seq_puts(s, " pid user virtual address size dma dir\n"); 22662306a36Sopenharmony_ci seq_puts(s, "----------------------------------------------------------\n"); 22762306a36Sopenharmony_ci } 22862306a36Sopenharmony_ci seq_printf(s, " %-7d 0x%-14llx %-10llu %-30s\n", 22962306a36Sopenharmony_ci userptr->pid, userptr->addr, userptr->size, 23062306a36Sopenharmony_ci dma_dir[userptr->dir]); 23162306a36Sopenharmony_ci } 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci spin_unlock(&dev_entry->userptr_spinlock); 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci if (!first) 23662306a36Sopenharmony_ci seq_puts(s, "\n"); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci return 0; 23962306a36Sopenharmony_ci} 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cistatic int vm_show(struct seq_file *s, void *data) 24262306a36Sopenharmony_ci{ 24362306a36Sopenharmony_ci struct hl_debugfs_entry *entry = s->private; 24462306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = entry->dev_entry; 24562306a36Sopenharmony_ci struct hl_vm_hw_block_list_node *lnode; 24662306a36Sopenharmony_ci struct hl_ctx *ctx; 24762306a36Sopenharmony_ci struct hl_vm *vm; 24862306a36Sopenharmony_ci struct hl_vm_hash_node *hnode; 24962306a36Sopenharmony_ci struct hl_userptr *userptr; 25062306a36Sopenharmony_ci struct hl_vm_phys_pg_pack *phys_pg_pack = NULL; 25162306a36Sopenharmony_ci struct hl_va_range *va_range; 25262306a36Sopenharmony_ci struct hl_vm_va_block *va_block; 25362306a36Sopenharmony_ci enum vm_type *vm_type; 25462306a36Sopenharmony_ci bool once = true; 25562306a36Sopenharmony_ci u64 j; 25662306a36Sopenharmony_ci int i; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci mutex_lock(&dev_entry->ctx_mem_hash_mutex); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci list_for_each_entry(ctx, &dev_entry->ctx_mem_hash_list, debugfs_list) { 26162306a36Sopenharmony_ci once = false; 26262306a36Sopenharmony_ci seq_puts(s, "\n\n----------------------------------------------------"); 26362306a36Sopenharmony_ci seq_puts(s, "\n----------------------------------------------------\n\n"); 26462306a36Sopenharmony_ci seq_printf(s, "ctx asid: %u\n", ctx->asid); 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci seq_puts(s, "\nmappings:\n\n"); 26762306a36Sopenharmony_ci seq_puts(s, " virtual address size handle\n"); 26862306a36Sopenharmony_ci seq_puts(s, "----------------------------------------------------\n"); 26962306a36Sopenharmony_ci mutex_lock(&ctx->mem_hash_lock); 27062306a36Sopenharmony_ci hash_for_each(ctx->mem_hash, i, hnode, node) { 27162306a36Sopenharmony_ci vm_type = hnode->ptr; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci if (*vm_type == VM_TYPE_USERPTR) { 27462306a36Sopenharmony_ci userptr = hnode->ptr; 27562306a36Sopenharmony_ci seq_printf(s, 27662306a36Sopenharmony_ci " 0x%-14llx %-10llu\n", 27762306a36Sopenharmony_ci hnode->vaddr, userptr->size); 27862306a36Sopenharmony_ci } else { 27962306a36Sopenharmony_ci phys_pg_pack = hnode->ptr; 28062306a36Sopenharmony_ci seq_printf(s, 28162306a36Sopenharmony_ci " 0x%-14llx %-10llu %-4u\n", 28262306a36Sopenharmony_ci hnode->vaddr, phys_pg_pack->total_size, 28362306a36Sopenharmony_ci phys_pg_pack->handle); 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci mutex_unlock(&ctx->mem_hash_lock); 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci if (ctx->asid != HL_KERNEL_ASID_ID && 28962306a36Sopenharmony_ci !list_empty(&ctx->hw_block_mem_list)) { 29062306a36Sopenharmony_ci seq_puts(s, "\nhw_block mappings:\n\n"); 29162306a36Sopenharmony_ci seq_puts(s, 29262306a36Sopenharmony_ci " virtual address block size mapped size HW block id\n"); 29362306a36Sopenharmony_ci seq_puts(s, 29462306a36Sopenharmony_ci "---------------------------------------------------------------\n"); 29562306a36Sopenharmony_ci mutex_lock(&ctx->hw_block_list_lock); 29662306a36Sopenharmony_ci list_for_each_entry(lnode, &ctx->hw_block_mem_list, node) { 29762306a36Sopenharmony_ci seq_printf(s, 29862306a36Sopenharmony_ci " 0x%-14lx %-6u %-6u %-9u\n", 29962306a36Sopenharmony_ci lnode->vaddr, lnode->block_size, lnode->mapped_size, 30062306a36Sopenharmony_ci lnode->id); 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci mutex_unlock(&ctx->hw_block_list_lock); 30362306a36Sopenharmony_ci } 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci vm = &ctx->hdev->vm; 30662306a36Sopenharmony_ci spin_lock(&vm->idr_lock); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci if (!idr_is_empty(&vm->phys_pg_pack_handles)) 30962306a36Sopenharmony_ci seq_puts(s, "\n\nallocations:\n"); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci idr_for_each_entry(&vm->phys_pg_pack_handles, phys_pg_pack, i) { 31262306a36Sopenharmony_ci if (phys_pg_pack->asid != ctx->asid) 31362306a36Sopenharmony_ci continue; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci seq_printf(s, "\nhandle: %u\n", phys_pg_pack->handle); 31662306a36Sopenharmony_ci seq_printf(s, "page size: %u\n\n", 31762306a36Sopenharmony_ci phys_pg_pack->page_size); 31862306a36Sopenharmony_ci seq_puts(s, " physical address\n"); 31962306a36Sopenharmony_ci seq_puts(s, "---------------------\n"); 32062306a36Sopenharmony_ci for (j = 0 ; j < phys_pg_pack->npages ; j++) { 32162306a36Sopenharmony_ci seq_printf(s, " 0x%-14llx\n", 32262306a36Sopenharmony_ci phys_pg_pack->pages[j]); 32362306a36Sopenharmony_ci } 32462306a36Sopenharmony_ci } 32562306a36Sopenharmony_ci spin_unlock(&vm->idr_lock); 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci } 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci mutex_unlock(&dev_entry->ctx_mem_hash_mutex); 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci ctx = hl_get_compute_ctx(dev_entry->hdev); 33262306a36Sopenharmony_ci if (ctx) { 33362306a36Sopenharmony_ci seq_puts(s, "\nVA ranges:\n\n"); 33462306a36Sopenharmony_ci for (i = HL_VA_RANGE_TYPE_HOST ; i < HL_VA_RANGE_TYPE_MAX ; ++i) { 33562306a36Sopenharmony_ci va_range = ctx->va_range[i]; 33662306a36Sopenharmony_ci seq_printf(s, " va_range %d\n", i); 33762306a36Sopenharmony_ci seq_puts(s, "---------------------\n"); 33862306a36Sopenharmony_ci mutex_lock(&va_range->lock); 33962306a36Sopenharmony_ci list_for_each_entry(va_block, &va_range->list, node) { 34062306a36Sopenharmony_ci seq_printf(s, "%#16llx - %#16llx (%#llx)\n", 34162306a36Sopenharmony_ci va_block->start, va_block->end, 34262306a36Sopenharmony_ci va_block->size); 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci mutex_unlock(&va_range->lock); 34562306a36Sopenharmony_ci seq_puts(s, "\n"); 34662306a36Sopenharmony_ci } 34762306a36Sopenharmony_ci hl_ctx_put(ctx); 34862306a36Sopenharmony_ci } 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci if (!once) 35162306a36Sopenharmony_ci seq_puts(s, "\n"); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci return 0; 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_cistatic int userptr_lookup_show(struct seq_file *s, void *data) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci struct hl_debugfs_entry *entry = s->private; 35962306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = entry->dev_entry; 36062306a36Sopenharmony_ci struct scatterlist *sg; 36162306a36Sopenharmony_ci struct hl_userptr *userptr; 36262306a36Sopenharmony_ci bool first = true; 36362306a36Sopenharmony_ci u64 total_npages, npages, sg_start, sg_end; 36462306a36Sopenharmony_ci dma_addr_t dma_addr; 36562306a36Sopenharmony_ci int i; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci spin_lock(&dev_entry->userptr_spinlock); 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci list_for_each_entry(userptr, &dev_entry->userptr_list, debugfs_list) { 37062306a36Sopenharmony_ci if (dev_entry->userptr_lookup >= userptr->addr && 37162306a36Sopenharmony_ci dev_entry->userptr_lookup < userptr->addr + userptr->size) { 37262306a36Sopenharmony_ci total_npages = 0; 37362306a36Sopenharmony_ci for_each_sgtable_dma_sg(userptr->sgt, sg, i) { 37462306a36Sopenharmony_ci npages = hl_get_sg_info(sg, &dma_addr); 37562306a36Sopenharmony_ci sg_start = userptr->addr + 37662306a36Sopenharmony_ci total_npages * PAGE_SIZE; 37762306a36Sopenharmony_ci sg_end = userptr->addr + 37862306a36Sopenharmony_ci (total_npages + npages) * PAGE_SIZE; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci if (dev_entry->userptr_lookup >= sg_start && 38162306a36Sopenharmony_ci dev_entry->userptr_lookup < sg_end) { 38262306a36Sopenharmony_ci dma_addr += (dev_entry->userptr_lookup - 38362306a36Sopenharmony_ci sg_start); 38462306a36Sopenharmony_ci if (first) { 38562306a36Sopenharmony_ci first = false; 38662306a36Sopenharmony_ci seq_puts(s, "\n"); 38762306a36Sopenharmony_ci seq_puts(s, " user virtual address dma address pid region start region size\n"); 38862306a36Sopenharmony_ci seq_puts(s, "---------------------------------------------------------------------------------------\n"); 38962306a36Sopenharmony_ci } 39062306a36Sopenharmony_ci seq_printf(s, " 0x%-18llx 0x%-16llx %-8u 0x%-16llx %-12llu\n", 39162306a36Sopenharmony_ci dev_entry->userptr_lookup, 39262306a36Sopenharmony_ci (u64)dma_addr, userptr->pid, 39362306a36Sopenharmony_ci userptr->addr, userptr->size); 39462306a36Sopenharmony_ci } 39562306a36Sopenharmony_ci total_npages += npages; 39662306a36Sopenharmony_ci } 39762306a36Sopenharmony_ci } 39862306a36Sopenharmony_ci } 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci spin_unlock(&dev_entry->userptr_spinlock); 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci if (!first) 40362306a36Sopenharmony_ci seq_puts(s, "\n"); 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci return 0; 40662306a36Sopenharmony_ci} 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_cistatic ssize_t userptr_lookup_write(struct file *file, const char __user *buf, 40962306a36Sopenharmony_ci size_t count, loff_t *f_pos) 41062306a36Sopenharmony_ci{ 41162306a36Sopenharmony_ci struct seq_file *s = file->private_data; 41262306a36Sopenharmony_ci struct hl_debugfs_entry *entry = s->private; 41362306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = entry->dev_entry; 41462306a36Sopenharmony_ci ssize_t rc; 41562306a36Sopenharmony_ci u64 value; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci rc = kstrtoull_from_user(buf, count, 16, &value); 41862306a36Sopenharmony_ci if (rc) 41962306a36Sopenharmony_ci return rc; 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci dev_entry->userptr_lookup = value; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci return count; 42462306a36Sopenharmony_ci} 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_cistatic int mmu_show(struct seq_file *s, void *data) 42762306a36Sopenharmony_ci{ 42862306a36Sopenharmony_ci struct hl_debugfs_entry *entry = s->private; 42962306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = entry->dev_entry; 43062306a36Sopenharmony_ci struct hl_device *hdev = dev_entry->hdev; 43162306a36Sopenharmony_ci struct hl_ctx *ctx; 43262306a36Sopenharmony_ci struct hl_mmu_hop_info hops_info = {0}; 43362306a36Sopenharmony_ci u64 virt_addr = dev_entry->mmu_addr, phys_addr; 43462306a36Sopenharmony_ci int i; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci if (dev_entry->mmu_asid == HL_KERNEL_ASID_ID) 43762306a36Sopenharmony_ci ctx = hdev->kernel_ctx; 43862306a36Sopenharmony_ci else 43962306a36Sopenharmony_ci ctx = hl_get_compute_ctx(hdev); 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci if (!ctx) { 44262306a36Sopenharmony_ci dev_err(hdev->dev, "no ctx available\n"); 44362306a36Sopenharmony_ci return 0; 44462306a36Sopenharmony_ci } 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci if (hl_mmu_get_tlb_info(ctx, virt_addr, &hops_info)) { 44762306a36Sopenharmony_ci dev_err(hdev->dev, "virt addr 0x%llx is not mapped to phys addr\n", 44862306a36Sopenharmony_ci virt_addr); 44962306a36Sopenharmony_ci goto put_ctx; 45062306a36Sopenharmony_ci } 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci hl_mmu_va_to_pa(ctx, virt_addr, &phys_addr); 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci if (hops_info.scrambled_vaddr && 45562306a36Sopenharmony_ci (dev_entry->mmu_addr != hops_info.scrambled_vaddr)) 45662306a36Sopenharmony_ci seq_printf(s, 45762306a36Sopenharmony_ci "asid: %u, virt_addr: 0x%llx, scrambled virt_addr: 0x%llx,\nphys_addr: 0x%llx, scrambled_phys_addr: 0x%llx\n", 45862306a36Sopenharmony_ci dev_entry->mmu_asid, dev_entry->mmu_addr, 45962306a36Sopenharmony_ci hops_info.scrambled_vaddr, 46062306a36Sopenharmony_ci hops_info.unscrambled_paddr, phys_addr); 46162306a36Sopenharmony_ci else 46262306a36Sopenharmony_ci seq_printf(s, 46362306a36Sopenharmony_ci "asid: %u, virt_addr: 0x%llx, phys_addr: 0x%llx\n", 46462306a36Sopenharmony_ci dev_entry->mmu_asid, dev_entry->mmu_addr, phys_addr); 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci for (i = 0 ; i < hops_info.used_hops ; i++) { 46762306a36Sopenharmony_ci seq_printf(s, "hop%d_addr: 0x%llx\n", 46862306a36Sopenharmony_ci i, hops_info.hop_info[i].hop_addr); 46962306a36Sopenharmony_ci seq_printf(s, "hop%d_pte_addr: 0x%llx\n", 47062306a36Sopenharmony_ci i, hops_info.hop_info[i].hop_pte_addr); 47162306a36Sopenharmony_ci seq_printf(s, "hop%d_pte: 0x%llx\n", 47262306a36Sopenharmony_ci i, hops_info.hop_info[i].hop_pte_val); 47362306a36Sopenharmony_ci } 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ciput_ctx: 47662306a36Sopenharmony_ci if (dev_entry->mmu_asid != HL_KERNEL_ASID_ID) 47762306a36Sopenharmony_ci hl_ctx_put(ctx); 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci return 0; 48062306a36Sopenharmony_ci} 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_cistatic ssize_t mmu_asid_va_write(struct file *file, const char __user *buf, 48362306a36Sopenharmony_ci size_t count, loff_t *f_pos) 48462306a36Sopenharmony_ci{ 48562306a36Sopenharmony_ci struct seq_file *s = file->private_data; 48662306a36Sopenharmony_ci struct hl_debugfs_entry *entry = s->private; 48762306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = entry->dev_entry; 48862306a36Sopenharmony_ci struct hl_device *hdev = dev_entry->hdev; 48962306a36Sopenharmony_ci char kbuf[MMU_KBUF_SIZE]; 49062306a36Sopenharmony_ci char *c; 49162306a36Sopenharmony_ci ssize_t rc; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci if (count > sizeof(kbuf) - 1) 49462306a36Sopenharmony_ci goto err; 49562306a36Sopenharmony_ci if (copy_from_user(kbuf, buf, count)) 49662306a36Sopenharmony_ci goto err; 49762306a36Sopenharmony_ci kbuf[count] = 0; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci c = strchr(kbuf, ' '); 50062306a36Sopenharmony_ci if (!c) 50162306a36Sopenharmony_ci goto err; 50262306a36Sopenharmony_ci *c = '\0'; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci rc = kstrtouint(kbuf, 10, &dev_entry->mmu_asid); 50562306a36Sopenharmony_ci if (rc) 50662306a36Sopenharmony_ci goto err; 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci if (strncmp(c+1, "0x", 2)) 50962306a36Sopenharmony_ci goto err; 51062306a36Sopenharmony_ci rc = kstrtoull(c+3, 16, &dev_entry->mmu_addr); 51162306a36Sopenharmony_ci if (rc) 51262306a36Sopenharmony_ci goto err; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci return count; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_cierr: 51762306a36Sopenharmony_ci dev_err(hdev->dev, "usage: echo <asid> <0xaddr> > mmu\n"); 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci return -EINVAL; 52062306a36Sopenharmony_ci} 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_cistatic int mmu_ack_error(struct seq_file *s, void *data) 52362306a36Sopenharmony_ci{ 52462306a36Sopenharmony_ci struct hl_debugfs_entry *entry = s->private; 52562306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = entry->dev_entry; 52662306a36Sopenharmony_ci struct hl_device *hdev = dev_entry->hdev; 52762306a36Sopenharmony_ci int rc; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci if (!dev_entry->mmu_cap_mask) { 53062306a36Sopenharmony_ci dev_err(hdev->dev, "mmu_cap_mask is not set\n"); 53162306a36Sopenharmony_ci goto err; 53262306a36Sopenharmony_ci } 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci rc = hdev->asic_funcs->ack_mmu_errors(hdev, dev_entry->mmu_cap_mask); 53562306a36Sopenharmony_ci if (rc) 53662306a36Sopenharmony_ci goto err; 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci return 0; 53962306a36Sopenharmony_cierr: 54062306a36Sopenharmony_ci return -EINVAL; 54162306a36Sopenharmony_ci} 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_cistatic ssize_t mmu_ack_error_value_write(struct file *file, 54462306a36Sopenharmony_ci const char __user *buf, 54562306a36Sopenharmony_ci size_t count, loff_t *f_pos) 54662306a36Sopenharmony_ci{ 54762306a36Sopenharmony_ci struct seq_file *s = file->private_data; 54862306a36Sopenharmony_ci struct hl_debugfs_entry *entry = s->private; 54962306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = entry->dev_entry; 55062306a36Sopenharmony_ci struct hl_device *hdev = dev_entry->hdev; 55162306a36Sopenharmony_ci char kbuf[MMU_KBUF_SIZE]; 55262306a36Sopenharmony_ci ssize_t rc; 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci if (count > sizeof(kbuf) - 1) 55562306a36Sopenharmony_ci goto err; 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci if (copy_from_user(kbuf, buf, count)) 55862306a36Sopenharmony_ci goto err; 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci kbuf[count] = 0; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci if (strncmp(kbuf, "0x", 2)) 56362306a36Sopenharmony_ci goto err; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci rc = kstrtoull(kbuf, 16, &dev_entry->mmu_cap_mask); 56662306a36Sopenharmony_ci if (rc) 56762306a36Sopenharmony_ci goto err; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci return count; 57062306a36Sopenharmony_cierr: 57162306a36Sopenharmony_ci dev_err(hdev->dev, "usage: echo <0xmmu_cap_mask > > mmu_error\n"); 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci return -EINVAL; 57462306a36Sopenharmony_ci} 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_cistatic int engines_show(struct seq_file *s, void *data) 57762306a36Sopenharmony_ci{ 57862306a36Sopenharmony_ci struct hl_debugfs_entry *entry = s->private; 57962306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = entry->dev_entry; 58062306a36Sopenharmony_ci struct hl_device *hdev = dev_entry->hdev; 58162306a36Sopenharmony_ci struct engines_data eng_data; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci if (hdev->reset_info.in_reset) { 58462306a36Sopenharmony_ci dev_warn_ratelimited(hdev->dev, 58562306a36Sopenharmony_ci "Can't check device idle during reset\n"); 58662306a36Sopenharmony_ci return 0; 58762306a36Sopenharmony_ci } 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci eng_data.actual_size = 0; 59062306a36Sopenharmony_ci eng_data.allocated_buf_size = HL_ENGINES_DATA_MAX_SIZE; 59162306a36Sopenharmony_ci eng_data.buf = vmalloc(eng_data.allocated_buf_size); 59262306a36Sopenharmony_ci if (!eng_data.buf) 59362306a36Sopenharmony_ci return -ENOMEM; 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci hdev->asic_funcs->is_device_idle(hdev, NULL, 0, &eng_data); 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci if (eng_data.actual_size > eng_data.allocated_buf_size) { 59862306a36Sopenharmony_ci dev_err(hdev->dev, 59962306a36Sopenharmony_ci "Engines data size (%d Bytes) is bigger than allocated size (%u Bytes)\n", 60062306a36Sopenharmony_ci eng_data.actual_size, eng_data.allocated_buf_size); 60162306a36Sopenharmony_ci vfree(eng_data.buf); 60262306a36Sopenharmony_ci return -ENOMEM; 60362306a36Sopenharmony_ci } 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci seq_write(s, eng_data.buf, eng_data.actual_size); 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci vfree(eng_data.buf); 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci return 0; 61062306a36Sopenharmony_ci} 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_cistatic ssize_t hl_memory_scrub(struct file *f, const char __user *buf, 61362306a36Sopenharmony_ci size_t count, loff_t *ppos) 61462306a36Sopenharmony_ci{ 61562306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 61662306a36Sopenharmony_ci struct hl_device *hdev = entry->hdev; 61762306a36Sopenharmony_ci u64 val = hdev->memory_scrub_val; 61862306a36Sopenharmony_ci int rc; 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci if (!hl_device_operational(hdev, NULL)) { 62162306a36Sopenharmony_ci dev_warn_ratelimited(hdev->dev, "Can't scrub memory, device is not operational\n"); 62262306a36Sopenharmony_ci return -EIO; 62362306a36Sopenharmony_ci } 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci mutex_lock(&hdev->fpriv_list_lock); 62662306a36Sopenharmony_ci if (hdev->is_compute_ctx_active) { 62762306a36Sopenharmony_ci mutex_unlock(&hdev->fpriv_list_lock); 62862306a36Sopenharmony_ci dev_err(hdev->dev, "can't scrub dram, context exist\n"); 62962306a36Sopenharmony_ci return -EBUSY; 63062306a36Sopenharmony_ci } 63162306a36Sopenharmony_ci hdev->is_in_dram_scrub = true; 63262306a36Sopenharmony_ci mutex_unlock(&hdev->fpriv_list_lock); 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci rc = hdev->asic_funcs->scrub_device_dram(hdev, val); 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci mutex_lock(&hdev->fpriv_list_lock); 63762306a36Sopenharmony_ci hdev->is_in_dram_scrub = false; 63862306a36Sopenharmony_ci mutex_unlock(&hdev->fpriv_list_lock); 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci if (rc) 64162306a36Sopenharmony_ci return rc; 64262306a36Sopenharmony_ci return count; 64362306a36Sopenharmony_ci} 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_cistatic bool hl_is_device_va(struct hl_device *hdev, u64 addr) 64662306a36Sopenharmony_ci{ 64762306a36Sopenharmony_ci struct asic_fixed_properties *prop = &hdev->asic_prop; 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci if (prop->dram_supports_virtual_memory && 65062306a36Sopenharmony_ci (addr >= prop->dmmu.start_addr && addr < prop->dmmu.end_addr)) 65162306a36Sopenharmony_ci return true; 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci if (addr >= prop->pmmu.start_addr && 65462306a36Sopenharmony_ci addr < prop->pmmu.end_addr) 65562306a36Sopenharmony_ci return true; 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci if (addr >= prop->pmmu_huge.start_addr && 65862306a36Sopenharmony_ci addr < prop->pmmu_huge.end_addr) 65962306a36Sopenharmony_ci return true; 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci return false; 66262306a36Sopenharmony_ci} 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_cistatic bool hl_is_device_internal_memory_va(struct hl_device *hdev, u64 addr, 66562306a36Sopenharmony_ci u32 size) 66662306a36Sopenharmony_ci{ 66762306a36Sopenharmony_ci struct asic_fixed_properties *prop = &hdev->asic_prop; 66862306a36Sopenharmony_ci u64 dram_start_addr, dram_end_addr; 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci if (prop->dram_supports_virtual_memory) { 67162306a36Sopenharmony_ci dram_start_addr = prop->dmmu.start_addr; 67262306a36Sopenharmony_ci dram_end_addr = prop->dmmu.end_addr; 67362306a36Sopenharmony_ci } else { 67462306a36Sopenharmony_ci dram_start_addr = prop->dram_base_address; 67562306a36Sopenharmony_ci dram_end_addr = prop->dram_end_address; 67662306a36Sopenharmony_ci } 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci if (hl_mem_area_inside_range(addr, size, dram_start_addr, 67962306a36Sopenharmony_ci dram_end_addr)) 68062306a36Sopenharmony_ci return true; 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci if (hl_mem_area_inside_range(addr, size, prop->sram_base_address, 68362306a36Sopenharmony_ci prop->sram_end_address)) 68462306a36Sopenharmony_ci return true; 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci return false; 68762306a36Sopenharmony_ci} 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_cistatic int device_va_to_pa(struct hl_device *hdev, u64 virt_addr, u32 size, 69062306a36Sopenharmony_ci u64 *phys_addr) 69162306a36Sopenharmony_ci{ 69262306a36Sopenharmony_ci struct hl_vm_phys_pg_pack *phys_pg_pack; 69362306a36Sopenharmony_ci struct hl_ctx *ctx; 69462306a36Sopenharmony_ci struct hl_vm_hash_node *hnode; 69562306a36Sopenharmony_ci u64 end_address, range_size; 69662306a36Sopenharmony_ci struct hl_userptr *userptr; 69762306a36Sopenharmony_ci enum vm_type *vm_type; 69862306a36Sopenharmony_ci bool valid = false; 69962306a36Sopenharmony_ci int i, rc = 0; 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci ctx = hl_get_compute_ctx(hdev); 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci if (!ctx) { 70462306a36Sopenharmony_ci dev_err(hdev->dev, "no ctx available\n"); 70562306a36Sopenharmony_ci return -EINVAL; 70662306a36Sopenharmony_ci } 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci /* Verify address is mapped */ 70962306a36Sopenharmony_ci mutex_lock(&ctx->mem_hash_lock); 71062306a36Sopenharmony_ci hash_for_each(ctx->mem_hash, i, hnode, node) { 71162306a36Sopenharmony_ci vm_type = hnode->ptr; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci if (*vm_type == VM_TYPE_USERPTR) { 71462306a36Sopenharmony_ci userptr = hnode->ptr; 71562306a36Sopenharmony_ci range_size = userptr->size; 71662306a36Sopenharmony_ci } else { 71762306a36Sopenharmony_ci phys_pg_pack = hnode->ptr; 71862306a36Sopenharmony_ci range_size = phys_pg_pack->total_size; 71962306a36Sopenharmony_ci } 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci end_address = virt_addr + size; 72262306a36Sopenharmony_ci if ((virt_addr >= hnode->vaddr) && 72362306a36Sopenharmony_ci (end_address <= hnode->vaddr + range_size)) { 72462306a36Sopenharmony_ci valid = true; 72562306a36Sopenharmony_ci break; 72662306a36Sopenharmony_ci } 72762306a36Sopenharmony_ci } 72862306a36Sopenharmony_ci mutex_unlock(&ctx->mem_hash_lock); 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci if (!valid) { 73162306a36Sopenharmony_ci dev_err(hdev->dev, 73262306a36Sopenharmony_ci "virt addr 0x%llx is not mapped\n", 73362306a36Sopenharmony_ci virt_addr); 73462306a36Sopenharmony_ci rc = -EINVAL; 73562306a36Sopenharmony_ci goto put_ctx; 73662306a36Sopenharmony_ci } 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci rc = hl_mmu_va_to_pa(ctx, virt_addr, phys_addr); 73962306a36Sopenharmony_ci if (rc) { 74062306a36Sopenharmony_ci dev_err(hdev->dev, 74162306a36Sopenharmony_ci "virt addr 0x%llx is not mapped to phys addr\n", 74262306a36Sopenharmony_ci virt_addr); 74362306a36Sopenharmony_ci rc = -EINVAL; 74462306a36Sopenharmony_ci } 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ciput_ctx: 74762306a36Sopenharmony_ci hl_ctx_put(ctx); 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci return rc; 75062306a36Sopenharmony_ci} 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_cistatic int hl_access_dev_mem_by_region(struct hl_device *hdev, u64 addr, 75362306a36Sopenharmony_ci u64 *val, enum debugfs_access_type acc_type, bool *found) 75462306a36Sopenharmony_ci{ 75562306a36Sopenharmony_ci size_t acc_size = (acc_type == DEBUGFS_READ64 || acc_type == DEBUGFS_WRITE64) ? 75662306a36Sopenharmony_ci sizeof(u64) : sizeof(u32); 75762306a36Sopenharmony_ci struct pci_mem_region *mem_reg; 75862306a36Sopenharmony_ci int i; 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci for (i = 0; i < PCI_REGION_NUMBER; i++) { 76162306a36Sopenharmony_ci mem_reg = &hdev->pci_mem_region[i]; 76262306a36Sopenharmony_ci if (!mem_reg->used) 76362306a36Sopenharmony_ci continue; 76462306a36Sopenharmony_ci if (addr >= mem_reg->region_base && 76562306a36Sopenharmony_ci addr <= mem_reg->region_base + mem_reg->region_size - acc_size) { 76662306a36Sopenharmony_ci *found = true; 76762306a36Sopenharmony_ci return hdev->asic_funcs->access_dev_mem(hdev, i, addr, val, acc_type); 76862306a36Sopenharmony_ci } 76962306a36Sopenharmony_ci } 77062306a36Sopenharmony_ci return 0; 77162306a36Sopenharmony_ci} 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_cistatic void hl_access_host_mem(struct hl_device *hdev, u64 addr, u64 *val, 77462306a36Sopenharmony_ci enum debugfs_access_type acc_type) 77562306a36Sopenharmony_ci{ 77662306a36Sopenharmony_ci struct asic_fixed_properties *prop = &hdev->asic_prop; 77762306a36Sopenharmony_ci u64 offset = prop->device_dma_offset_for_host_access; 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci switch (acc_type) { 78062306a36Sopenharmony_ci case DEBUGFS_READ32: 78162306a36Sopenharmony_ci *val = *(u32 *) phys_to_virt(addr - offset); 78262306a36Sopenharmony_ci break; 78362306a36Sopenharmony_ci case DEBUGFS_WRITE32: 78462306a36Sopenharmony_ci *(u32 *) phys_to_virt(addr - offset) = *val; 78562306a36Sopenharmony_ci break; 78662306a36Sopenharmony_ci case DEBUGFS_READ64: 78762306a36Sopenharmony_ci *val = *(u64 *) phys_to_virt(addr - offset); 78862306a36Sopenharmony_ci break; 78962306a36Sopenharmony_ci case DEBUGFS_WRITE64: 79062306a36Sopenharmony_ci *(u64 *) phys_to_virt(addr - offset) = *val; 79162306a36Sopenharmony_ci break; 79262306a36Sopenharmony_ci default: 79362306a36Sopenharmony_ci dev_err(hdev->dev, "hostmem access-type %d id not supported\n", acc_type); 79462306a36Sopenharmony_ci break; 79562306a36Sopenharmony_ci } 79662306a36Sopenharmony_ci} 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_cistatic int hl_access_mem(struct hl_device *hdev, u64 addr, u64 *val, 79962306a36Sopenharmony_ci enum debugfs_access_type acc_type) 80062306a36Sopenharmony_ci{ 80162306a36Sopenharmony_ci size_t acc_size = (acc_type == DEBUGFS_READ64 || acc_type == DEBUGFS_WRITE64) ? 80262306a36Sopenharmony_ci sizeof(u64) : sizeof(u32); 80362306a36Sopenharmony_ci u64 host_start = hdev->asic_prop.host_base_address; 80462306a36Sopenharmony_ci u64 host_end = hdev->asic_prop.host_end_address; 80562306a36Sopenharmony_ci bool user_address, found = false; 80662306a36Sopenharmony_ci int rc; 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci user_address = hl_is_device_va(hdev, addr); 80962306a36Sopenharmony_ci if (user_address) { 81062306a36Sopenharmony_ci rc = device_va_to_pa(hdev, addr, acc_size, &addr); 81162306a36Sopenharmony_ci if (rc) 81262306a36Sopenharmony_ci return rc; 81362306a36Sopenharmony_ci } 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci rc = hl_access_dev_mem_by_region(hdev, addr, val, acc_type, &found); 81662306a36Sopenharmony_ci if (rc) { 81762306a36Sopenharmony_ci dev_err(hdev->dev, 81862306a36Sopenharmony_ci "Failed reading addr %#llx from dev mem (%d)\n", 81962306a36Sopenharmony_ci addr, rc); 82062306a36Sopenharmony_ci return rc; 82162306a36Sopenharmony_ci } 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci if (found) 82462306a36Sopenharmony_ci return 0; 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci if (!user_address || device_iommu_mapped(&hdev->pdev->dev)) { 82762306a36Sopenharmony_ci rc = -EINVAL; 82862306a36Sopenharmony_ci goto err; 82962306a36Sopenharmony_ci } 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci if (addr >= host_start && addr <= host_end - acc_size) { 83262306a36Sopenharmony_ci hl_access_host_mem(hdev, addr, val, acc_type); 83362306a36Sopenharmony_ci } else { 83462306a36Sopenharmony_ci rc = -EINVAL; 83562306a36Sopenharmony_ci goto err; 83662306a36Sopenharmony_ci } 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci return 0; 83962306a36Sopenharmony_cierr: 84062306a36Sopenharmony_ci dev_err(hdev->dev, "invalid addr %#llx\n", addr); 84162306a36Sopenharmony_ci return rc; 84262306a36Sopenharmony_ci} 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_cistatic ssize_t hl_data_read32(struct file *f, char __user *buf, 84562306a36Sopenharmony_ci size_t count, loff_t *ppos) 84662306a36Sopenharmony_ci{ 84762306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 84862306a36Sopenharmony_ci struct hl_device *hdev = entry->hdev; 84962306a36Sopenharmony_ci u64 value64, addr = entry->addr; 85062306a36Sopenharmony_ci char tmp_buf[32]; 85162306a36Sopenharmony_ci ssize_t rc; 85262306a36Sopenharmony_ci u32 val; 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci if (hdev->reset_info.in_reset) { 85562306a36Sopenharmony_ci dev_warn_ratelimited(hdev->dev, "Can't read during reset\n"); 85662306a36Sopenharmony_ci return 0; 85762306a36Sopenharmony_ci } 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci if (*ppos) 86062306a36Sopenharmony_ci return 0; 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci rc = hl_access_mem(hdev, addr, &value64, DEBUGFS_READ32); 86362306a36Sopenharmony_ci if (rc) 86462306a36Sopenharmony_ci return rc; 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci val = value64; /* downcast back to 32 */ 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci sprintf(tmp_buf, "0x%08x\n", val); 86962306a36Sopenharmony_ci return simple_read_from_buffer(buf, count, ppos, tmp_buf, 87062306a36Sopenharmony_ci strlen(tmp_buf)); 87162306a36Sopenharmony_ci} 87262306a36Sopenharmony_ci 87362306a36Sopenharmony_cistatic ssize_t hl_data_write32(struct file *f, const char __user *buf, 87462306a36Sopenharmony_ci size_t count, loff_t *ppos) 87562306a36Sopenharmony_ci{ 87662306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 87762306a36Sopenharmony_ci struct hl_device *hdev = entry->hdev; 87862306a36Sopenharmony_ci u64 value64, addr = entry->addr; 87962306a36Sopenharmony_ci u32 value; 88062306a36Sopenharmony_ci ssize_t rc; 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci if (hdev->reset_info.in_reset) { 88362306a36Sopenharmony_ci dev_warn_ratelimited(hdev->dev, "Can't write during reset\n"); 88462306a36Sopenharmony_ci return 0; 88562306a36Sopenharmony_ci } 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci rc = kstrtouint_from_user(buf, count, 16, &value); 88862306a36Sopenharmony_ci if (rc) 88962306a36Sopenharmony_ci return rc; 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci value64 = value; 89262306a36Sopenharmony_ci rc = hl_access_mem(hdev, addr, &value64, DEBUGFS_WRITE32); 89362306a36Sopenharmony_ci if (rc) 89462306a36Sopenharmony_ci return rc; 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci return count; 89762306a36Sopenharmony_ci} 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_cistatic ssize_t hl_data_read64(struct file *f, char __user *buf, 90062306a36Sopenharmony_ci size_t count, loff_t *ppos) 90162306a36Sopenharmony_ci{ 90262306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 90362306a36Sopenharmony_ci struct hl_device *hdev = entry->hdev; 90462306a36Sopenharmony_ci u64 addr = entry->addr; 90562306a36Sopenharmony_ci char tmp_buf[32]; 90662306a36Sopenharmony_ci ssize_t rc; 90762306a36Sopenharmony_ci u64 val; 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci if (hdev->reset_info.in_reset) { 91062306a36Sopenharmony_ci dev_warn_ratelimited(hdev->dev, "Can't read during reset\n"); 91162306a36Sopenharmony_ci return 0; 91262306a36Sopenharmony_ci } 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci if (*ppos) 91562306a36Sopenharmony_ci return 0; 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci rc = hl_access_mem(hdev, addr, &val, DEBUGFS_READ64); 91862306a36Sopenharmony_ci if (rc) 91962306a36Sopenharmony_ci return rc; 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci sprintf(tmp_buf, "0x%016llx\n", val); 92262306a36Sopenharmony_ci return simple_read_from_buffer(buf, count, ppos, tmp_buf, 92362306a36Sopenharmony_ci strlen(tmp_buf)); 92462306a36Sopenharmony_ci} 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_cistatic ssize_t hl_data_write64(struct file *f, const char __user *buf, 92762306a36Sopenharmony_ci size_t count, loff_t *ppos) 92862306a36Sopenharmony_ci{ 92962306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 93062306a36Sopenharmony_ci struct hl_device *hdev = entry->hdev; 93162306a36Sopenharmony_ci u64 addr = entry->addr; 93262306a36Sopenharmony_ci u64 value; 93362306a36Sopenharmony_ci ssize_t rc; 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ci if (hdev->reset_info.in_reset) { 93662306a36Sopenharmony_ci dev_warn_ratelimited(hdev->dev, "Can't write during reset\n"); 93762306a36Sopenharmony_ci return 0; 93862306a36Sopenharmony_ci } 93962306a36Sopenharmony_ci 94062306a36Sopenharmony_ci rc = kstrtoull_from_user(buf, count, 16, &value); 94162306a36Sopenharmony_ci if (rc) 94262306a36Sopenharmony_ci return rc; 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci rc = hl_access_mem(hdev, addr, &value, DEBUGFS_WRITE64); 94562306a36Sopenharmony_ci if (rc) 94662306a36Sopenharmony_ci return rc; 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci return count; 94962306a36Sopenharmony_ci} 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_cistatic ssize_t hl_dma_size_write(struct file *f, const char __user *buf, 95262306a36Sopenharmony_ci size_t count, loff_t *ppos) 95362306a36Sopenharmony_ci{ 95462306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 95562306a36Sopenharmony_ci struct hl_device *hdev = entry->hdev; 95662306a36Sopenharmony_ci u64 addr = entry->addr; 95762306a36Sopenharmony_ci ssize_t rc; 95862306a36Sopenharmony_ci u32 size; 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci if (hdev->reset_info.in_reset) { 96162306a36Sopenharmony_ci dev_warn_ratelimited(hdev->dev, "Can't DMA during reset\n"); 96262306a36Sopenharmony_ci return 0; 96362306a36Sopenharmony_ci } 96462306a36Sopenharmony_ci rc = kstrtouint_from_user(buf, count, 16, &size); 96562306a36Sopenharmony_ci if (rc) 96662306a36Sopenharmony_ci return rc; 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_ci if (!size) { 96962306a36Sopenharmony_ci dev_err(hdev->dev, "DMA read failed. size can't be 0\n"); 97062306a36Sopenharmony_ci return -EINVAL; 97162306a36Sopenharmony_ci } 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci if (size > SZ_128M) { 97462306a36Sopenharmony_ci dev_err(hdev->dev, 97562306a36Sopenharmony_ci "DMA read failed. size can't be larger than 128MB\n"); 97662306a36Sopenharmony_ci return -EINVAL; 97762306a36Sopenharmony_ci } 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci if (!hl_is_device_internal_memory_va(hdev, addr, size)) { 98062306a36Sopenharmony_ci dev_err(hdev->dev, 98162306a36Sopenharmony_ci "DMA read failed. Invalid 0x%010llx + 0x%08x\n", 98262306a36Sopenharmony_ci addr, size); 98362306a36Sopenharmony_ci return -EINVAL; 98462306a36Sopenharmony_ci } 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci /* Free the previous allocation, if there was any */ 98762306a36Sopenharmony_ci entry->data_dma_blob_desc.size = 0; 98862306a36Sopenharmony_ci vfree(entry->data_dma_blob_desc.data); 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci entry->data_dma_blob_desc.data = vmalloc(size); 99162306a36Sopenharmony_ci if (!entry->data_dma_blob_desc.data) 99262306a36Sopenharmony_ci return -ENOMEM; 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ci rc = hdev->asic_funcs->debugfs_read_dma(hdev, addr, size, 99562306a36Sopenharmony_ci entry->data_dma_blob_desc.data); 99662306a36Sopenharmony_ci if (rc) { 99762306a36Sopenharmony_ci dev_err(hdev->dev, "Failed to DMA from 0x%010llx\n", addr); 99862306a36Sopenharmony_ci vfree(entry->data_dma_blob_desc.data); 99962306a36Sopenharmony_ci entry->data_dma_blob_desc.data = NULL; 100062306a36Sopenharmony_ci return -EIO; 100162306a36Sopenharmony_ci } 100262306a36Sopenharmony_ci 100362306a36Sopenharmony_ci entry->data_dma_blob_desc.size = size; 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_ci return count; 100662306a36Sopenharmony_ci} 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_cistatic ssize_t hl_monitor_dump_trigger(struct file *f, const char __user *buf, 100962306a36Sopenharmony_ci size_t count, loff_t *ppos) 101062306a36Sopenharmony_ci{ 101162306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 101262306a36Sopenharmony_ci struct hl_device *hdev = entry->hdev; 101362306a36Sopenharmony_ci u32 size, trig; 101462306a36Sopenharmony_ci ssize_t rc; 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci if (hdev->reset_info.in_reset) { 101762306a36Sopenharmony_ci dev_warn_ratelimited(hdev->dev, "Can't dump monitors during reset\n"); 101862306a36Sopenharmony_ci return 0; 101962306a36Sopenharmony_ci } 102062306a36Sopenharmony_ci rc = kstrtouint_from_user(buf, count, 10, &trig); 102162306a36Sopenharmony_ci if (rc) 102262306a36Sopenharmony_ci return rc; 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci if (trig != 1) { 102562306a36Sopenharmony_ci dev_err(hdev->dev, "Must write 1 to trigger monitor dump\n"); 102662306a36Sopenharmony_ci return -EINVAL; 102762306a36Sopenharmony_ci } 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ci size = sizeof(struct cpucp_monitor_dump); 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_ci /* Free the previous allocation, if there was any */ 103262306a36Sopenharmony_ci entry->mon_dump_blob_desc.size = 0; 103362306a36Sopenharmony_ci vfree(entry->mon_dump_blob_desc.data); 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci entry->mon_dump_blob_desc.data = vmalloc(size); 103662306a36Sopenharmony_ci if (!entry->mon_dump_blob_desc.data) 103762306a36Sopenharmony_ci return -ENOMEM; 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci rc = hdev->asic_funcs->get_monitor_dump(hdev, entry->mon_dump_blob_desc.data); 104062306a36Sopenharmony_ci if (rc) { 104162306a36Sopenharmony_ci dev_err(hdev->dev, "Failed to dump monitors\n"); 104262306a36Sopenharmony_ci vfree(entry->mon_dump_blob_desc.data); 104362306a36Sopenharmony_ci entry->mon_dump_blob_desc.data = NULL; 104462306a36Sopenharmony_ci return -EIO; 104562306a36Sopenharmony_ci } 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci entry->mon_dump_blob_desc.size = size; 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci return count; 105062306a36Sopenharmony_ci} 105162306a36Sopenharmony_ci 105262306a36Sopenharmony_cistatic ssize_t hl_get_power_state(struct file *f, char __user *buf, 105362306a36Sopenharmony_ci size_t count, loff_t *ppos) 105462306a36Sopenharmony_ci{ 105562306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 105662306a36Sopenharmony_ci struct hl_device *hdev = entry->hdev; 105762306a36Sopenharmony_ci char tmp_buf[200]; 105862306a36Sopenharmony_ci int i; 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci if (*ppos) 106162306a36Sopenharmony_ci return 0; 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci if (hdev->pdev->current_state == PCI_D0) 106462306a36Sopenharmony_ci i = 1; 106562306a36Sopenharmony_ci else if (hdev->pdev->current_state == PCI_D3hot) 106662306a36Sopenharmony_ci i = 2; 106762306a36Sopenharmony_ci else 106862306a36Sopenharmony_ci i = 3; 106962306a36Sopenharmony_ci 107062306a36Sopenharmony_ci sprintf(tmp_buf, 107162306a36Sopenharmony_ci "current power state: %d\n1 - D0\n2 - D3hot\n3 - Unknown\n", i); 107262306a36Sopenharmony_ci return simple_read_from_buffer(buf, count, ppos, tmp_buf, 107362306a36Sopenharmony_ci strlen(tmp_buf)); 107462306a36Sopenharmony_ci} 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_cistatic ssize_t hl_set_power_state(struct file *f, const char __user *buf, 107762306a36Sopenharmony_ci size_t count, loff_t *ppos) 107862306a36Sopenharmony_ci{ 107962306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 108062306a36Sopenharmony_ci struct hl_device *hdev = entry->hdev; 108162306a36Sopenharmony_ci u32 value; 108262306a36Sopenharmony_ci ssize_t rc; 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_ci rc = kstrtouint_from_user(buf, count, 10, &value); 108562306a36Sopenharmony_ci if (rc) 108662306a36Sopenharmony_ci return rc; 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci if (value == 1) { 108962306a36Sopenharmony_ci pci_set_power_state(hdev->pdev, PCI_D0); 109062306a36Sopenharmony_ci pci_restore_state(hdev->pdev); 109162306a36Sopenharmony_ci rc = pci_enable_device(hdev->pdev); 109262306a36Sopenharmony_ci if (rc < 0) 109362306a36Sopenharmony_ci return rc; 109462306a36Sopenharmony_ci } else if (value == 2) { 109562306a36Sopenharmony_ci pci_save_state(hdev->pdev); 109662306a36Sopenharmony_ci pci_disable_device(hdev->pdev); 109762306a36Sopenharmony_ci pci_set_power_state(hdev->pdev, PCI_D3hot); 109862306a36Sopenharmony_ci } else { 109962306a36Sopenharmony_ci dev_dbg(hdev->dev, "invalid power state value %u\n", value); 110062306a36Sopenharmony_ci return -EINVAL; 110162306a36Sopenharmony_ci } 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci return count; 110462306a36Sopenharmony_ci} 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_cistatic ssize_t hl_i2c_data_read(struct file *f, char __user *buf, 110762306a36Sopenharmony_ci size_t count, loff_t *ppos) 110862306a36Sopenharmony_ci{ 110962306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 111062306a36Sopenharmony_ci struct hl_device *hdev = entry->hdev; 111162306a36Sopenharmony_ci char tmp_buf[32]; 111262306a36Sopenharmony_ci u64 val; 111362306a36Sopenharmony_ci ssize_t rc; 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_ci if (*ppos) 111662306a36Sopenharmony_ci return 0; 111762306a36Sopenharmony_ci 111862306a36Sopenharmony_ci rc = hl_debugfs_i2c_read(hdev, entry->i2c_bus, entry->i2c_addr, 111962306a36Sopenharmony_ci entry->i2c_reg, entry->i2c_len, &val); 112062306a36Sopenharmony_ci if (rc) { 112162306a36Sopenharmony_ci dev_err(hdev->dev, 112262306a36Sopenharmony_ci "Failed to read from I2C bus %d, addr %d, reg %d, len %d\n", 112362306a36Sopenharmony_ci entry->i2c_bus, entry->i2c_addr, entry->i2c_reg, entry->i2c_len); 112462306a36Sopenharmony_ci return rc; 112562306a36Sopenharmony_ci } 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_ci sprintf(tmp_buf, "%#02llx\n", val); 112862306a36Sopenharmony_ci rc = simple_read_from_buffer(buf, count, ppos, tmp_buf, 112962306a36Sopenharmony_ci strlen(tmp_buf)); 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci return rc; 113262306a36Sopenharmony_ci} 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_cistatic ssize_t hl_i2c_data_write(struct file *f, const char __user *buf, 113562306a36Sopenharmony_ci size_t count, loff_t *ppos) 113662306a36Sopenharmony_ci{ 113762306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 113862306a36Sopenharmony_ci struct hl_device *hdev = entry->hdev; 113962306a36Sopenharmony_ci u64 value; 114062306a36Sopenharmony_ci ssize_t rc; 114162306a36Sopenharmony_ci 114262306a36Sopenharmony_ci rc = kstrtou64_from_user(buf, count, 16, &value); 114362306a36Sopenharmony_ci if (rc) 114462306a36Sopenharmony_ci return rc; 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci rc = hl_debugfs_i2c_write(hdev, entry->i2c_bus, entry->i2c_addr, 114762306a36Sopenharmony_ci entry->i2c_reg, entry->i2c_len, value); 114862306a36Sopenharmony_ci if (rc) { 114962306a36Sopenharmony_ci dev_err(hdev->dev, 115062306a36Sopenharmony_ci "Failed to write %#02llx to I2C bus %d, addr %d, reg %d, len %d\n", 115162306a36Sopenharmony_ci value, entry->i2c_bus, entry->i2c_addr, entry->i2c_reg, entry->i2c_len); 115262306a36Sopenharmony_ci return rc; 115362306a36Sopenharmony_ci } 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_ci return count; 115662306a36Sopenharmony_ci} 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_cistatic ssize_t hl_led0_write(struct file *f, const char __user *buf, 115962306a36Sopenharmony_ci size_t count, loff_t *ppos) 116062306a36Sopenharmony_ci{ 116162306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 116262306a36Sopenharmony_ci struct hl_device *hdev = entry->hdev; 116362306a36Sopenharmony_ci u32 value; 116462306a36Sopenharmony_ci ssize_t rc; 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_ci rc = kstrtouint_from_user(buf, count, 10, &value); 116762306a36Sopenharmony_ci if (rc) 116862306a36Sopenharmony_ci return rc; 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci value = value ? 1 : 0; 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_ci hl_debugfs_led_set(hdev, 0, value); 117362306a36Sopenharmony_ci 117462306a36Sopenharmony_ci return count; 117562306a36Sopenharmony_ci} 117662306a36Sopenharmony_ci 117762306a36Sopenharmony_cistatic ssize_t hl_led1_write(struct file *f, const char __user *buf, 117862306a36Sopenharmony_ci size_t count, loff_t *ppos) 117962306a36Sopenharmony_ci{ 118062306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 118162306a36Sopenharmony_ci struct hl_device *hdev = entry->hdev; 118262306a36Sopenharmony_ci u32 value; 118362306a36Sopenharmony_ci ssize_t rc; 118462306a36Sopenharmony_ci 118562306a36Sopenharmony_ci rc = kstrtouint_from_user(buf, count, 10, &value); 118662306a36Sopenharmony_ci if (rc) 118762306a36Sopenharmony_ci return rc; 118862306a36Sopenharmony_ci 118962306a36Sopenharmony_ci value = value ? 1 : 0; 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci hl_debugfs_led_set(hdev, 1, value); 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_ci return count; 119462306a36Sopenharmony_ci} 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_cistatic ssize_t hl_led2_write(struct file *f, const char __user *buf, 119762306a36Sopenharmony_ci size_t count, loff_t *ppos) 119862306a36Sopenharmony_ci{ 119962306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 120062306a36Sopenharmony_ci struct hl_device *hdev = entry->hdev; 120162306a36Sopenharmony_ci u32 value; 120262306a36Sopenharmony_ci ssize_t rc; 120362306a36Sopenharmony_ci 120462306a36Sopenharmony_ci rc = kstrtouint_from_user(buf, count, 10, &value); 120562306a36Sopenharmony_ci if (rc) 120662306a36Sopenharmony_ci return rc; 120762306a36Sopenharmony_ci 120862306a36Sopenharmony_ci value = value ? 1 : 0; 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci hl_debugfs_led_set(hdev, 2, value); 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ci return count; 121362306a36Sopenharmony_ci} 121462306a36Sopenharmony_ci 121562306a36Sopenharmony_cistatic ssize_t hl_device_read(struct file *f, char __user *buf, 121662306a36Sopenharmony_ci size_t count, loff_t *ppos) 121762306a36Sopenharmony_ci{ 121862306a36Sopenharmony_ci static const char *help = 121962306a36Sopenharmony_ci "Valid values: disable, enable, suspend, resume, cpu_timeout\n"; 122062306a36Sopenharmony_ci return simple_read_from_buffer(buf, count, ppos, help, strlen(help)); 122162306a36Sopenharmony_ci} 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_cistatic ssize_t hl_device_write(struct file *f, const char __user *buf, 122462306a36Sopenharmony_ci size_t count, loff_t *ppos) 122562306a36Sopenharmony_ci{ 122662306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 122762306a36Sopenharmony_ci struct hl_device *hdev = entry->hdev; 122862306a36Sopenharmony_ci char data[30] = {0}; 122962306a36Sopenharmony_ci 123062306a36Sopenharmony_ci /* don't allow partial writes */ 123162306a36Sopenharmony_ci if (*ppos != 0) 123262306a36Sopenharmony_ci return 0; 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci simple_write_to_buffer(data, 29, ppos, buf, count); 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_ci if (strncmp("disable", data, strlen("disable")) == 0) { 123762306a36Sopenharmony_ci hdev->disabled = true; 123862306a36Sopenharmony_ci } else if (strncmp("enable", data, strlen("enable")) == 0) { 123962306a36Sopenharmony_ci hdev->disabled = false; 124062306a36Sopenharmony_ci } else if (strncmp("suspend", data, strlen("suspend")) == 0) { 124162306a36Sopenharmony_ci hdev->asic_funcs->suspend(hdev); 124262306a36Sopenharmony_ci } else if (strncmp("resume", data, strlen("resume")) == 0) { 124362306a36Sopenharmony_ci hdev->asic_funcs->resume(hdev); 124462306a36Sopenharmony_ci } else if (strncmp("cpu_timeout", data, strlen("cpu_timeout")) == 0) { 124562306a36Sopenharmony_ci hdev->device_cpu_disabled = true; 124662306a36Sopenharmony_ci } else { 124762306a36Sopenharmony_ci dev_err(hdev->dev, 124862306a36Sopenharmony_ci "Valid values: disable, enable, suspend, resume, cpu_timeout\n"); 124962306a36Sopenharmony_ci count = -EINVAL; 125062306a36Sopenharmony_ci } 125162306a36Sopenharmony_ci 125262306a36Sopenharmony_ci return count; 125362306a36Sopenharmony_ci} 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_cistatic ssize_t hl_clk_gate_read(struct file *f, char __user *buf, 125662306a36Sopenharmony_ci size_t count, loff_t *ppos) 125762306a36Sopenharmony_ci{ 125862306a36Sopenharmony_ci return 0; 125962306a36Sopenharmony_ci} 126062306a36Sopenharmony_ci 126162306a36Sopenharmony_cistatic ssize_t hl_clk_gate_write(struct file *f, const char __user *buf, 126262306a36Sopenharmony_ci size_t count, loff_t *ppos) 126362306a36Sopenharmony_ci{ 126462306a36Sopenharmony_ci return count; 126562306a36Sopenharmony_ci} 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_cistatic ssize_t hl_stop_on_err_read(struct file *f, char __user *buf, 126862306a36Sopenharmony_ci size_t count, loff_t *ppos) 126962306a36Sopenharmony_ci{ 127062306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 127162306a36Sopenharmony_ci struct hl_device *hdev = entry->hdev; 127262306a36Sopenharmony_ci char tmp_buf[200]; 127362306a36Sopenharmony_ci ssize_t rc; 127462306a36Sopenharmony_ci 127562306a36Sopenharmony_ci if (!hdev->asic_prop.configurable_stop_on_err) 127662306a36Sopenharmony_ci return -EOPNOTSUPP; 127762306a36Sopenharmony_ci 127862306a36Sopenharmony_ci if (*ppos) 127962306a36Sopenharmony_ci return 0; 128062306a36Sopenharmony_ci 128162306a36Sopenharmony_ci sprintf(tmp_buf, "%d\n", hdev->stop_on_err); 128262306a36Sopenharmony_ci rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf, 128362306a36Sopenharmony_ci strlen(tmp_buf) + 1); 128462306a36Sopenharmony_ci 128562306a36Sopenharmony_ci return rc; 128662306a36Sopenharmony_ci} 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_cistatic ssize_t hl_stop_on_err_write(struct file *f, const char __user *buf, 128962306a36Sopenharmony_ci size_t count, loff_t *ppos) 129062306a36Sopenharmony_ci{ 129162306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 129262306a36Sopenharmony_ci struct hl_device *hdev = entry->hdev; 129362306a36Sopenharmony_ci u32 value; 129462306a36Sopenharmony_ci ssize_t rc; 129562306a36Sopenharmony_ci 129662306a36Sopenharmony_ci if (!hdev->asic_prop.configurable_stop_on_err) 129762306a36Sopenharmony_ci return -EOPNOTSUPP; 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_ci if (hdev->reset_info.in_reset) { 130062306a36Sopenharmony_ci dev_warn_ratelimited(hdev->dev, 130162306a36Sopenharmony_ci "Can't change stop on error during reset\n"); 130262306a36Sopenharmony_ci return 0; 130362306a36Sopenharmony_ci } 130462306a36Sopenharmony_ci 130562306a36Sopenharmony_ci rc = kstrtouint_from_user(buf, count, 10, &value); 130662306a36Sopenharmony_ci if (rc) 130762306a36Sopenharmony_ci return rc; 130862306a36Sopenharmony_ci 130962306a36Sopenharmony_ci hdev->stop_on_err = value ? 1 : 0; 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_ci hl_device_reset(hdev, 0); 131262306a36Sopenharmony_ci 131362306a36Sopenharmony_ci return count; 131462306a36Sopenharmony_ci} 131562306a36Sopenharmony_ci 131662306a36Sopenharmony_cistatic ssize_t hl_security_violations_read(struct file *f, char __user *buf, 131762306a36Sopenharmony_ci size_t count, loff_t *ppos) 131862306a36Sopenharmony_ci{ 131962306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 132062306a36Sopenharmony_ci struct hl_device *hdev = entry->hdev; 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci hdev->asic_funcs->ack_protection_bits_errors(hdev); 132362306a36Sopenharmony_ci 132462306a36Sopenharmony_ci return 0; 132562306a36Sopenharmony_ci} 132662306a36Sopenharmony_ci 132762306a36Sopenharmony_cistatic ssize_t hl_state_dump_read(struct file *f, char __user *buf, 132862306a36Sopenharmony_ci size_t count, loff_t *ppos) 132962306a36Sopenharmony_ci{ 133062306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 133162306a36Sopenharmony_ci ssize_t rc; 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci down_read(&entry->state_dump_sem); 133462306a36Sopenharmony_ci if (!entry->state_dump[entry->state_dump_head]) 133562306a36Sopenharmony_ci rc = 0; 133662306a36Sopenharmony_ci else 133762306a36Sopenharmony_ci rc = simple_read_from_buffer( 133862306a36Sopenharmony_ci buf, count, ppos, 133962306a36Sopenharmony_ci entry->state_dump[entry->state_dump_head], 134062306a36Sopenharmony_ci strlen(entry->state_dump[entry->state_dump_head])); 134162306a36Sopenharmony_ci up_read(&entry->state_dump_sem); 134262306a36Sopenharmony_ci 134362306a36Sopenharmony_ci return rc; 134462306a36Sopenharmony_ci} 134562306a36Sopenharmony_ci 134662306a36Sopenharmony_cistatic ssize_t hl_state_dump_write(struct file *f, const char __user *buf, 134762306a36Sopenharmony_ci size_t count, loff_t *ppos) 134862306a36Sopenharmony_ci{ 134962306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 135062306a36Sopenharmony_ci struct hl_device *hdev = entry->hdev; 135162306a36Sopenharmony_ci ssize_t rc; 135262306a36Sopenharmony_ci u32 size; 135362306a36Sopenharmony_ci int i; 135462306a36Sopenharmony_ci 135562306a36Sopenharmony_ci rc = kstrtouint_from_user(buf, count, 10, &size); 135662306a36Sopenharmony_ci if (rc) 135762306a36Sopenharmony_ci return rc; 135862306a36Sopenharmony_ci 135962306a36Sopenharmony_ci if (size <= 0 || size >= ARRAY_SIZE(entry->state_dump)) { 136062306a36Sopenharmony_ci dev_err(hdev->dev, "Invalid number of dumps to skip\n"); 136162306a36Sopenharmony_ci return -EINVAL; 136262306a36Sopenharmony_ci } 136362306a36Sopenharmony_ci 136462306a36Sopenharmony_ci if (entry->state_dump[entry->state_dump_head]) { 136562306a36Sopenharmony_ci down_write(&entry->state_dump_sem); 136662306a36Sopenharmony_ci for (i = 0; i < size; ++i) { 136762306a36Sopenharmony_ci vfree(entry->state_dump[entry->state_dump_head]); 136862306a36Sopenharmony_ci entry->state_dump[entry->state_dump_head] = NULL; 136962306a36Sopenharmony_ci if (entry->state_dump_head > 0) 137062306a36Sopenharmony_ci entry->state_dump_head--; 137162306a36Sopenharmony_ci else 137262306a36Sopenharmony_ci entry->state_dump_head = 137362306a36Sopenharmony_ci ARRAY_SIZE(entry->state_dump) - 1; 137462306a36Sopenharmony_ci } 137562306a36Sopenharmony_ci up_write(&entry->state_dump_sem); 137662306a36Sopenharmony_ci } 137762306a36Sopenharmony_ci 137862306a36Sopenharmony_ci return count; 137962306a36Sopenharmony_ci} 138062306a36Sopenharmony_ci 138162306a36Sopenharmony_cistatic ssize_t hl_timeout_locked_read(struct file *f, char __user *buf, 138262306a36Sopenharmony_ci size_t count, loff_t *ppos) 138362306a36Sopenharmony_ci{ 138462306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 138562306a36Sopenharmony_ci struct hl_device *hdev = entry->hdev; 138662306a36Sopenharmony_ci char tmp_buf[200]; 138762306a36Sopenharmony_ci ssize_t rc; 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ci if (*ppos) 139062306a36Sopenharmony_ci return 0; 139162306a36Sopenharmony_ci 139262306a36Sopenharmony_ci sprintf(tmp_buf, "%d\n", 139362306a36Sopenharmony_ci jiffies_to_msecs(hdev->timeout_jiffies) / 1000); 139462306a36Sopenharmony_ci rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf, 139562306a36Sopenharmony_ci strlen(tmp_buf) + 1); 139662306a36Sopenharmony_ci 139762306a36Sopenharmony_ci return rc; 139862306a36Sopenharmony_ci} 139962306a36Sopenharmony_ci 140062306a36Sopenharmony_cistatic ssize_t hl_timeout_locked_write(struct file *f, const char __user *buf, 140162306a36Sopenharmony_ci size_t count, loff_t *ppos) 140262306a36Sopenharmony_ci{ 140362306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 140462306a36Sopenharmony_ci struct hl_device *hdev = entry->hdev; 140562306a36Sopenharmony_ci u32 value; 140662306a36Sopenharmony_ci ssize_t rc; 140762306a36Sopenharmony_ci 140862306a36Sopenharmony_ci rc = kstrtouint_from_user(buf, count, 10, &value); 140962306a36Sopenharmony_ci if (rc) 141062306a36Sopenharmony_ci return rc; 141162306a36Sopenharmony_ci 141262306a36Sopenharmony_ci if (value) 141362306a36Sopenharmony_ci hdev->timeout_jiffies = msecs_to_jiffies(value * 1000); 141462306a36Sopenharmony_ci else 141562306a36Sopenharmony_ci hdev->timeout_jiffies = MAX_SCHEDULE_TIMEOUT; 141662306a36Sopenharmony_ci 141762306a36Sopenharmony_ci return count; 141862306a36Sopenharmony_ci} 141962306a36Sopenharmony_ci 142062306a36Sopenharmony_cistatic ssize_t hl_check_razwi_happened(struct file *f, char __user *buf, 142162306a36Sopenharmony_ci size_t count, loff_t *ppos) 142262306a36Sopenharmony_ci{ 142362306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = file_inode(f)->i_private; 142462306a36Sopenharmony_ci struct hl_device *hdev = entry->hdev; 142562306a36Sopenharmony_ci 142662306a36Sopenharmony_ci hdev->asic_funcs->check_if_razwi_happened(hdev); 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ci return 0; 142962306a36Sopenharmony_ci} 143062306a36Sopenharmony_ci 143162306a36Sopenharmony_cistatic const struct file_operations hl_mem_scrub_fops = { 143262306a36Sopenharmony_ci .owner = THIS_MODULE, 143362306a36Sopenharmony_ci .write = hl_memory_scrub, 143462306a36Sopenharmony_ci}; 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_cistatic const struct file_operations hl_data32b_fops = { 143762306a36Sopenharmony_ci .owner = THIS_MODULE, 143862306a36Sopenharmony_ci .read = hl_data_read32, 143962306a36Sopenharmony_ci .write = hl_data_write32 144062306a36Sopenharmony_ci}; 144162306a36Sopenharmony_ci 144262306a36Sopenharmony_cistatic const struct file_operations hl_data64b_fops = { 144362306a36Sopenharmony_ci .owner = THIS_MODULE, 144462306a36Sopenharmony_ci .read = hl_data_read64, 144562306a36Sopenharmony_ci .write = hl_data_write64 144662306a36Sopenharmony_ci}; 144762306a36Sopenharmony_ci 144862306a36Sopenharmony_cistatic const struct file_operations hl_dma_size_fops = { 144962306a36Sopenharmony_ci .owner = THIS_MODULE, 145062306a36Sopenharmony_ci .write = hl_dma_size_write 145162306a36Sopenharmony_ci}; 145262306a36Sopenharmony_ci 145362306a36Sopenharmony_cistatic const struct file_operations hl_monitor_dump_fops = { 145462306a36Sopenharmony_ci .owner = THIS_MODULE, 145562306a36Sopenharmony_ci .write = hl_monitor_dump_trigger 145662306a36Sopenharmony_ci}; 145762306a36Sopenharmony_ci 145862306a36Sopenharmony_cistatic const struct file_operations hl_i2c_data_fops = { 145962306a36Sopenharmony_ci .owner = THIS_MODULE, 146062306a36Sopenharmony_ci .read = hl_i2c_data_read, 146162306a36Sopenharmony_ci .write = hl_i2c_data_write 146262306a36Sopenharmony_ci}; 146362306a36Sopenharmony_ci 146462306a36Sopenharmony_cistatic const struct file_operations hl_power_fops = { 146562306a36Sopenharmony_ci .owner = THIS_MODULE, 146662306a36Sopenharmony_ci .read = hl_get_power_state, 146762306a36Sopenharmony_ci .write = hl_set_power_state 146862306a36Sopenharmony_ci}; 146962306a36Sopenharmony_ci 147062306a36Sopenharmony_cistatic const struct file_operations hl_led0_fops = { 147162306a36Sopenharmony_ci .owner = THIS_MODULE, 147262306a36Sopenharmony_ci .write = hl_led0_write 147362306a36Sopenharmony_ci}; 147462306a36Sopenharmony_ci 147562306a36Sopenharmony_cistatic const struct file_operations hl_led1_fops = { 147662306a36Sopenharmony_ci .owner = THIS_MODULE, 147762306a36Sopenharmony_ci .write = hl_led1_write 147862306a36Sopenharmony_ci}; 147962306a36Sopenharmony_ci 148062306a36Sopenharmony_cistatic const struct file_operations hl_led2_fops = { 148162306a36Sopenharmony_ci .owner = THIS_MODULE, 148262306a36Sopenharmony_ci .write = hl_led2_write 148362306a36Sopenharmony_ci}; 148462306a36Sopenharmony_ci 148562306a36Sopenharmony_cistatic const struct file_operations hl_device_fops = { 148662306a36Sopenharmony_ci .owner = THIS_MODULE, 148762306a36Sopenharmony_ci .read = hl_device_read, 148862306a36Sopenharmony_ci .write = hl_device_write 148962306a36Sopenharmony_ci}; 149062306a36Sopenharmony_ci 149162306a36Sopenharmony_cistatic const struct file_operations hl_clk_gate_fops = { 149262306a36Sopenharmony_ci .owner = THIS_MODULE, 149362306a36Sopenharmony_ci .read = hl_clk_gate_read, 149462306a36Sopenharmony_ci .write = hl_clk_gate_write 149562306a36Sopenharmony_ci}; 149662306a36Sopenharmony_ci 149762306a36Sopenharmony_cistatic const struct file_operations hl_stop_on_err_fops = { 149862306a36Sopenharmony_ci .owner = THIS_MODULE, 149962306a36Sopenharmony_ci .read = hl_stop_on_err_read, 150062306a36Sopenharmony_ci .write = hl_stop_on_err_write 150162306a36Sopenharmony_ci}; 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_cistatic const struct file_operations hl_security_violations_fops = { 150462306a36Sopenharmony_ci .owner = THIS_MODULE, 150562306a36Sopenharmony_ci .read = hl_security_violations_read 150662306a36Sopenharmony_ci}; 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_cistatic const struct file_operations hl_state_dump_fops = { 150962306a36Sopenharmony_ci .owner = THIS_MODULE, 151062306a36Sopenharmony_ci .read = hl_state_dump_read, 151162306a36Sopenharmony_ci .write = hl_state_dump_write 151262306a36Sopenharmony_ci}; 151362306a36Sopenharmony_ci 151462306a36Sopenharmony_cistatic const struct file_operations hl_timeout_locked_fops = { 151562306a36Sopenharmony_ci .owner = THIS_MODULE, 151662306a36Sopenharmony_ci .read = hl_timeout_locked_read, 151762306a36Sopenharmony_ci .write = hl_timeout_locked_write 151862306a36Sopenharmony_ci}; 151962306a36Sopenharmony_ci 152062306a36Sopenharmony_cistatic const struct file_operations hl_razwi_check_fops = { 152162306a36Sopenharmony_ci .owner = THIS_MODULE, 152262306a36Sopenharmony_ci .read = hl_check_razwi_happened 152362306a36Sopenharmony_ci}; 152462306a36Sopenharmony_ci 152562306a36Sopenharmony_cistatic const struct hl_info_list hl_debugfs_list[] = { 152662306a36Sopenharmony_ci {"command_buffers", command_buffers_show, NULL}, 152762306a36Sopenharmony_ci {"command_submission", command_submission_show, NULL}, 152862306a36Sopenharmony_ci {"command_submission_jobs", command_submission_jobs_show, NULL}, 152962306a36Sopenharmony_ci {"userptr", userptr_show, NULL}, 153062306a36Sopenharmony_ci {"vm", vm_show, NULL}, 153162306a36Sopenharmony_ci {"userptr_lookup", userptr_lookup_show, userptr_lookup_write}, 153262306a36Sopenharmony_ci {"mmu", mmu_show, mmu_asid_va_write}, 153362306a36Sopenharmony_ci {"mmu_error", mmu_ack_error, mmu_ack_error_value_write}, 153462306a36Sopenharmony_ci {"engines", engines_show, NULL}, 153562306a36Sopenharmony_ci}; 153662306a36Sopenharmony_ci 153762306a36Sopenharmony_cistatic int hl_debugfs_open(struct inode *inode, struct file *file) 153862306a36Sopenharmony_ci{ 153962306a36Sopenharmony_ci struct hl_debugfs_entry *node = inode->i_private; 154062306a36Sopenharmony_ci 154162306a36Sopenharmony_ci return single_open(file, node->info_ent->show, node); 154262306a36Sopenharmony_ci} 154362306a36Sopenharmony_ci 154462306a36Sopenharmony_cistatic ssize_t hl_debugfs_write(struct file *file, const char __user *buf, 154562306a36Sopenharmony_ci size_t count, loff_t *f_pos) 154662306a36Sopenharmony_ci{ 154762306a36Sopenharmony_ci struct hl_debugfs_entry *node = file->f_inode->i_private; 154862306a36Sopenharmony_ci 154962306a36Sopenharmony_ci if (node->info_ent->write) 155062306a36Sopenharmony_ci return node->info_ent->write(file, buf, count, f_pos); 155162306a36Sopenharmony_ci else 155262306a36Sopenharmony_ci return -EINVAL; 155362306a36Sopenharmony_ci 155462306a36Sopenharmony_ci} 155562306a36Sopenharmony_ci 155662306a36Sopenharmony_cistatic const struct file_operations hl_debugfs_fops = { 155762306a36Sopenharmony_ci .owner = THIS_MODULE, 155862306a36Sopenharmony_ci .open = hl_debugfs_open, 155962306a36Sopenharmony_ci .read = seq_read, 156062306a36Sopenharmony_ci .write = hl_debugfs_write, 156162306a36Sopenharmony_ci .llseek = seq_lseek, 156262306a36Sopenharmony_ci .release = single_release, 156362306a36Sopenharmony_ci}; 156462306a36Sopenharmony_ci 156562306a36Sopenharmony_cistatic void add_secured_nodes(struct hl_dbg_device_entry *dev_entry, struct dentry *root) 156662306a36Sopenharmony_ci{ 156762306a36Sopenharmony_ci debugfs_create_u8("i2c_bus", 156862306a36Sopenharmony_ci 0644, 156962306a36Sopenharmony_ci root, 157062306a36Sopenharmony_ci &dev_entry->i2c_bus); 157162306a36Sopenharmony_ci 157262306a36Sopenharmony_ci debugfs_create_u8("i2c_addr", 157362306a36Sopenharmony_ci 0644, 157462306a36Sopenharmony_ci root, 157562306a36Sopenharmony_ci &dev_entry->i2c_addr); 157662306a36Sopenharmony_ci 157762306a36Sopenharmony_ci debugfs_create_u8("i2c_reg", 157862306a36Sopenharmony_ci 0644, 157962306a36Sopenharmony_ci root, 158062306a36Sopenharmony_ci &dev_entry->i2c_reg); 158162306a36Sopenharmony_ci 158262306a36Sopenharmony_ci debugfs_create_u8("i2c_len", 158362306a36Sopenharmony_ci 0644, 158462306a36Sopenharmony_ci root, 158562306a36Sopenharmony_ci &dev_entry->i2c_len); 158662306a36Sopenharmony_ci 158762306a36Sopenharmony_ci debugfs_create_file("i2c_data", 158862306a36Sopenharmony_ci 0644, 158962306a36Sopenharmony_ci root, 159062306a36Sopenharmony_ci dev_entry, 159162306a36Sopenharmony_ci &hl_i2c_data_fops); 159262306a36Sopenharmony_ci 159362306a36Sopenharmony_ci debugfs_create_file("led0", 159462306a36Sopenharmony_ci 0200, 159562306a36Sopenharmony_ci root, 159662306a36Sopenharmony_ci dev_entry, 159762306a36Sopenharmony_ci &hl_led0_fops); 159862306a36Sopenharmony_ci 159962306a36Sopenharmony_ci debugfs_create_file("led1", 160062306a36Sopenharmony_ci 0200, 160162306a36Sopenharmony_ci root, 160262306a36Sopenharmony_ci dev_entry, 160362306a36Sopenharmony_ci &hl_led1_fops); 160462306a36Sopenharmony_ci 160562306a36Sopenharmony_ci debugfs_create_file("led2", 160662306a36Sopenharmony_ci 0200, 160762306a36Sopenharmony_ci root, 160862306a36Sopenharmony_ci dev_entry, 160962306a36Sopenharmony_ci &hl_led2_fops); 161062306a36Sopenharmony_ci} 161162306a36Sopenharmony_ci 161262306a36Sopenharmony_cistatic void add_files_to_device(struct hl_device *hdev, struct hl_dbg_device_entry *dev_entry, 161362306a36Sopenharmony_ci struct dentry *root) 161462306a36Sopenharmony_ci{ 161562306a36Sopenharmony_ci int count = ARRAY_SIZE(hl_debugfs_list); 161662306a36Sopenharmony_ci struct hl_debugfs_entry *entry; 161762306a36Sopenharmony_ci int i; 161862306a36Sopenharmony_ci 161962306a36Sopenharmony_ci debugfs_create_x64("memory_scrub_val", 162062306a36Sopenharmony_ci 0644, 162162306a36Sopenharmony_ci root, 162262306a36Sopenharmony_ci &hdev->memory_scrub_val); 162362306a36Sopenharmony_ci 162462306a36Sopenharmony_ci debugfs_create_file("memory_scrub", 162562306a36Sopenharmony_ci 0200, 162662306a36Sopenharmony_ci root, 162762306a36Sopenharmony_ci dev_entry, 162862306a36Sopenharmony_ci &hl_mem_scrub_fops); 162962306a36Sopenharmony_ci 163062306a36Sopenharmony_ci debugfs_create_x64("addr", 163162306a36Sopenharmony_ci 0644, 163262306a36Sopenharmony_ci root, 163362306a36Sopenharmony_ci &dev_entry->addr); 163462306a36Sopenharmony_ci 163562306a36Sopenharmony_ci debugfs_create_file("data32", 163662306a36Sopenharmony_ci 0644, 163762306a36Sopenharmony_ci root, 163862306a36Sopenharmony_ci dev_entry, 163962306a36Sopenharmony_ci &hl_data32b_fops); 164062306a36Sopenharmony_ci 164162306a36Sopenharmony_ci debugfs_create_file("data64", 164262306a36Sopenharmony_ci 0644, 164362306a36Sopenharmony_ci root, 164462306a36Sopenharmony_ci dev_entry, 164562306a36Sopenharmony_ci &hl_data64b_fops); 164662306a36Sopenharmony_ci 164762306a36Sopenharmony_ci debugfs_create_file("set_power_state", 164862306a36Sopenharmony_ci 0200, 164962306a36Sopenharmony_ci root, 165062306a36Sopenharmony_ci dev_entry, 165162306a36Sopenharmony_ci &hl_power_fops); 165262306a36Sopenharmony_ci 165362306a36Sopenharmony_ci debugfs_create_file("device", 165462306a36Sopenharmony_ci 0200, 165562306a36Sopenharmony_ci root, 165662306a36Sopenharmony_ci dev_entry, 165762306a36Sopenharmony_ci &hl_device_fops); 165862306a36Sopenharmony_ci 165962306a36Sopenharmony_ci debugfs_create_file("clk_gate", 166062306a36Sopenharmony_ci 0200, 166162306a36Sopenharmony_ci root, 166262306a36Sopenharmony_ci dev_entry, 166362306a36Sopenharmony_ci &hl_clk_gate_fops); 166462306a36Sopenharmony_ci 166562306a36Sopenharmony_ci debugfs_create_file("stop_on_err", 166662306a36Sopenharmony_ci 0644, 166762306a36Sopenharmony_ci root, 166862306a36Sopenharmony_ci dev_entry, 166962306a36Sopenharmony_ci &hl_stop_on_err_fops); 167062306a36Sopenharmony_ci 167162306a36Sopenharmony_ci debugfs_create_file("dump_security_violations", 167262306a36Sopenharmony_ci 0644, 167362306a36Sopenharmony_ci root, 167462306a36Sopenharmony_ci dev_entry, 167562306a36Sopenharmony_ci &hl_security_violations_fops); 167662306a36Sopenharmony_ci 167762306a36Sopenharmony_ci debugfs_create_file("dump_razwi_events", 167862306a36Sopenharmony_ci 0644, 167962306a36Sopenharmony_ci root, 168062306a36Sopenharmony_ci dev_entry, 168162306a36Sopenharmony_ci &hl_razwi_check_fops); 168262306a36Sopenharmony_ci 168362306a36Sopenharmony_ci debugfs_create_file("dma_size", 168462306a36Sopenharmony_ci 0200, 168562306a36Sopenharmony_ci root, 168662306a36Sopenharmony_ci dev_entry, 168762306a36Sopenharmony_ci &hl_dma_size_fops); 168862306a36Sopenharmony_ci 168962306a36Sopenharmony_ci debugfs_create_blob("data_dma", 169062306a36Sopenharmony_ci 0400, 169162306a36Sopenharmony_ci root, 169262306a36Sopenharmony_ci &dev_entry->data_dma_blob_desc); 169362306a36Sopenharmony_ci 169462306a36Sopenharmony_ci debugfs_create_file("monitor_dump_trig", 169562306a36Sopenharmony_ci 0200, 169662306a36Sopenharmony_ci root, 169762306a36Sopenharmony_ci dev_entry, 169862306a36Sopenharmony_ci &hl_monitor_dump_fops); 169962306a36Sopenharmony_ci 170062306a36Sopenharmony_ci debugfs_create_blob("monitor_dump", 170162306a36Sopenharmony_ci 0400, 170262306a36Sopenharmony_ci root, 170362306a36Sopenharmony_ci &dev_entry->mon_dump_blob_desc); 170462306a36Sopenharmony_ci 170562306a36Sopenharmony_ci debugfs_create_x8("skip_reset_on_timeout", 170662306a36Sopenharmony_ci 0644, 170762306a36Sopenharmony_ci root, 170862306a36Sopenharmony_ci &hdev->reset_info.skip_reset_on_timeout); 170962306a36Sopenharmony_ci 171062306a36Sopenharmony_ci debugfs_create_file("state_dump", 171162306a36Sopenharmony_ci 0600, 171262306a36Sopenharmony_ci root, 171362306a36Sopenharmony_ci dev_entry, 171462306a36Sopenharmony_ci &hl_state_dump_fops); 171562306a36Sopenharmony_ci 171662306a36Sopenharmony_ci debugfs_create_file("timeout_locked", 171762306a36Sopenharmony_ci 0644, 171862306a36Sopenharmony_ci root, 171962306a36Sopenharmony_ci dev_entry, 172062306a36Sopenharmony_ci &hl_timeout_locked_fops); 172162306a36Sopenharmony_ci 172262306a36Sopenharmony_ci debugfs_create_u32("device_release_watchdog_timeout", 172362306a36Sopenharmony_ci 0644, 172462306a36Sopenharmony_ci root, 172562306a36Sopenharmony_ci &hdev->device_release_watchdog_timeout_sec); 172662306a36Sopenharmony_ci 172762306a36Sopenharmony_ci for (i = 0, entry = dev_entry->entry_arr ; i < count ; i++, entry++) { 172862306a36Sopenharmony_ci debugfs_create_file(hl_debugfs_list[i].name, 172962306a36Sopenharmony_ci 0444, 173062306a36Sopenharmony_ci root, 173162306a36Sopenharmony_ci entry, 173262306a36Sopenharmony_ci &hl_debugfs_fops); 173362306a36Sopenharmony_ci entry->info_ent = &hl_debugfs_list[i]; 173462306a36Sopenharmony_ci entry->dev_entry = dev_entry; 173562306a36Sopenharmony_ci } 173662306a36Sopenharmony_ci} 173762306a36Sopenharmony_ci 173862306a36Sopenharmony_ciint hl_debugfs_device_init(struct hl_device *hdev) 173962306a36Sopenharmony_ci{ 174062306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs; 174162306a36Sopenharmony_ci int count = ARRAY_SIZE(hl_debugfs_list); 174262306a36Sopenharmony_ci 174362306a36Sopenharmony_ci dev_entry->hdev = hdev; 174462306a36Sopenharmony_ci dev_entry->entry_arr = kmalloc_array(count, sizeof(struct hl_debugfs_entry), GFP_KERNEL); 174562306a36Sopenharmony_ci if (!dev_entry->entry_arr) 174662306a36Sopenharmony_ci return -ENOMEM; 174762306a36Sopenharmony_ci 174862306a36Sopenharmony_ci dev_entry->data_dma_blob_desc.size = 0; 174962306a36Sopenharmony_ci dev_entry->data_dma_blob_desc.data = NULL; 175062306a36Sopenharmony_ci dev_entry->mon_dump_blob_desc.size = 0; 175162306a36Sopenharmony_ci dev_entry->mon_dump_blob_desc.data = NULL; 175262306a36Sopenharmony_ci 175362306a36Sopenharmony_ci INIT_LIST_HEAD(&dev_entry->file_list); 175462306a36Sopenharmony_ci INIT_LIST_HEAD(&dev_entry->cb_list); 175562306a36Sopenharmony_ci INIT_LIST_HEAD(&dev_entry->cs_list); 175662306a36Sopenharmony_ci INIT_LIST_HEAD(&dev_entry->cs_job_list); 175762306a36Sopenharmony_ci INIT_LIST_HEAD(&dev_entry->userptr_list); 175862306a36Sopenharmony_ci INIT_LIST_HEAD(&dev_entry->ctx_mem_hash_list); 175962306a36Sopenharmony_ci mutex_init(&dev_entry->file_mutex); 176062306a36Sopenharmony_ci init_rwsem(&dev_entry->state_dump_sem); 176162306a36Sopenharmony_ci spin_lock_init(&dev_entry->cb_spinlock); 176262306a36Sopenharmony_ci spin_lock_init(&dev_entry->cs_spinlock); 176362306a36Sopenharmony_ci spin_lock_init(&dev_entry->cs_job_spinlock); 176462306a36Sopenharmony_ci spin_lock_init(&dev_entry->userptr_spinlock); 176562306a36Sopenharmony_ci mutex_init(&dev_entry->ctx_mem_hash_mutex); 176662306a36Sopenharmony_ci 176762306a36Sopenharmony_ci return 0; 176862306a36Sopenharmony_ci} 176962306a36Sopenharmony_ci 177062306a36Sopenharmony_civoid hl_debugfs_device_fini(struct hl_device *hdev) 177162306a36Sopenharmony_ci{ 177262306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = &hdev->hl_debugfs; 177362306a36Sopenharmony_ci int i; 177462306a36Sopenharmony_ci 177562306a36Sopenharmony_ci mutex_destroy(&entry->ctx_mem_hash_mutex); 177662306a36Sopenharmony_ci mutex_destroy(&entry->file_mutex); 177762306a36Sopenharmony_ci 177862306a36Sopenharmony_ci vfree(entry->data_dma_blob_desc.data); 177962306a36Sopenharmony_ci vfree(entry->mon_dump_blob_desc.data); 178062306a36Sopenharmony_ci 178162306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(entry->state_dump); ++i) 178262306a36Sopenharmony_ci vfree(entry->state_dump[i]); 178362306a36Sopenharmony_ci 178462306a36Sopenharmony_ci kfree(entry->entry_arr); 178562306a36Sopenharmony_ci} 178662306a36Sopenharmony_ci 178762306a36Sopenharmony_civoid hl_debugfs_add_device(struct hl_device *hdev) 178862306a36Sopenharmony_ci{ 178962306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs; 179062306a36Sopenharmony_ci 179162306a36Sopenharmony_ci dev_entry->root = debugfs_create_dir(dev_name(hdev->dev), hl_debug_root); 179262306a36Sopenharmony_ci 179362306a36Sopenharmony_ci add_files_to_device(hdev, dev_entry, dev_entry->root); 179462306a36Sopenharmony_ci if (!hdev->asic_prop.fw_security_enabled) 179562306a36Sopenharmony_ci add_secured_nodes(dev_entry, dev_entry->root); 179662306a36Sopenharmony_ci} 179762306a36Sopenharmony_ci 179862306a36Sopenharmony_civoid hl_debugfs_remove_device(struct hl_device *hdev) 179962306a36Sopenharmony_ci{ 180062306a36Sopenharmony_ci struct hl_dbg_device_entry *entry = &hdev->hl_debugfs; 180162306a36Sopenharmony_ci 180262306a36Sopenharmony_ci debugfs_remove_recursive(entry->root); 180362306a36Sopenharmony_ci} 180462306a36Sopenharmony_ci 180562306a36Sopenharmony_civoid hl_debugfs_add_file(struct hl_fpriv *hpriv) 180662306a36Sopenharmony_ci{ 180762306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = &hpriv->hdev->hl_debugfs; 180862306a36Sopenharmony_ci 180962306a36Sopenharmony_ci mutex_lock(&dev_entry->file_mutex); 181062306a36Sopenharmony_ci list_add(&hpriv->debugfs_list, &dev_entry->file_list); 181162306a36Sopenharmony_ci mutex_unlock(&dev_entry->file_mutex); 181262306a36Sopenharmony_ci} 181362306a36Sopenharmony_ci 181462306a36Sopenharmony_civoid hl_debugfs_remove_file(struct hl_fpriv *hpriv) 181562306a36Sopenharmony_ci{ 181662306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = &hpriv->hdev->hl_debugfs; 181762306a36Sopenharmony_ci 181862306a36Sopenharmony_ci mutex_lock(&dev_entry->file_mutex); 181962306a36Sopenharmony_ci list_del(&hpriv->debugfs_list); 182062306a36Sopenharmony_ci mutex_unlock(&dev_entry->file_mutex); 182162306a36Sopenharmony_ci} 182262306a36Sopenharmony_ci 182362306a36Sopenharmony_civoid hl_debugfs_add_cb(struct hl_cb *cb) 182462306a36Sopenharmony_ci{ 182562306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = &cb->hdev->hl_debugfs; 182662306a36Sopenharmony_ci 182762306a36Sopenharmony_ci spin_lock(&dev_entry->cb_spinlock); 182862306a36Sopenharmony_ci list_add(&cb->debugfs_list, &dev_entry->cb_list); 182962306a36Sopenharmony_ci spin_unlock(&dev_entry->cb_spinlock); 183062306a36Sopenharmony_ci} 183162306a36Sopenharmony_ci 183262306a36Sopenharmony_civoid hl_debugfs_remove_cb(struct hl_cb *cb) 183362306a36Sopenharmony_ci{ 183462306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = &cb->hdev->hl_debugfs; 183562306a36Sopenharmony_ci 183662306a36Sopenharmony_ci spin_lock(&dev_entry->cb_spinlock); 183762306a36Sopenharmony_ci list_del(&cb->debugfs_list); 183862306a36Sopenharmony_ci spin_unlock(&dev_entry->cb_spinlock); 183962306a36Sopenharmony_ci} 184062306a36Sopenharmony_ci 184162306a36Sopenharmony_civoid hl_debugfs_add_cs(struct hl_cs *cs) 184262306a36Sopenharmony_ci{ 184362306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = &cs->ctx->hdev->hl_debugfs; 184462306a36Sopenharmony_ci 184562306a36Sopenharmony_ci spin_lock(&dev_entry->cs_spinlock); 184662306a36Sopenharmony_ci list_add(&cs->debugfs_list, &dev_entry->cs_list); 184762306a36Sopenharmony_ci spin_unlock(&dev_entry->cs_spinlock); 184862306a36Sopenharmony_ci} 184962306a36Sopenharmony_ci 185062306a36Sopenharmony_civoid hl_debugfs_remove_cs(struct hl_cs *cs) 185162306a36Sopenharmony_ci{ 185262306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = &cs->ctx->hdev->hl_debugfs; 185362306a36Sopenharmony_ci 185462306a36Sopenharmony_ci spin_lock(&dev_entry->cs_spinlock); 185562306a36Sopenharmony_ci list_del(&cs->debugfs_list); 185662306a36Sopenharmony_ci spin_unlock(&dev_entry->cs_spinlock); 185762306a36Sopenharmony_ci} 185862306a36Sopenharmony_ci 185962306a36Sopenharmony_civoid hl_debugfs_add_job(struct hl_device *hdev, struct hl_cs_job *job) 186062306a36Sopenharmony_ci{ 186162306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs; 186262306a36Sopenharmony_ci 186362306a36Sopenharmony_ci spin_lock(&dev_entry->cs_job_spinlock); 186462306a36Sopenharmony_ci list_add(&job->debugfs_list, &dev_entry->cs_job_list); 186562306a36Sopenharmony_ci spin_unlock(&dev_entry->cs_job_spinlock); 186662306a36Sopenharmony_ci} 186762306a36Sopenharmony_ci 186862306a36Sopenharmony_civoid hl_debugfs_remove_job(struct hl_device *hdev, struct hl_cs_job *job) 186962306a36Sopenharmony_ci{ 187062306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs; 187162306a36Sopenharmony_ci 187262306a36Sopenharmony_ci spin_lock(&dev_entry->cs_job_spinlock); 187362306a36Sopenharmony_ci list_del(&job->debugfs_list); 187462306a36Sopenharmony_ci spin_unlock(&dev_entry->cs_job_spinlock); 187562306a36Sopenharmony_ci} 187662306a36Sopenharmony_ci 187762306a36Sopenharmony_civoid hl_debugfs_add_userptr(struct hl_device *hdev, struct hl_userptr *userptr) 187862306a36Sopenharmony_ci{ 187962306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs; 188062306a36Sopenharmony_ci 188162306a36Sopenharmony_ci spin_lock(&dev_entry->userptr_spinlock); 188262306a36Sopenharmony_ci list_add(&userptr->debugfs_list, &dev_entry->userptr_list); 188362306a36Sopenharmony_ci spin_unlock(&dev_entry->userptr_spinlock); 188462306a36Sopenharmony_ci} 188562306a36Sopenharmony_ci 188662306a36Sopenharmony_civoid hl_debugfs_remove_userptr(struct hl_device *hdev, 188762306a36Sopenharmony_ci struct hl_userptr *userptr) 188862306a36Sopenharmony_ci{ 188962306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs; 189062306a36Sopenharmony_ci 189162306a36Sopenharmony_ci spin_lock(&dev_entry->userptr_spinlock); 189262306a36Sopenharmony_ci list_del(&userptr->debugfs_list); 189362306a36Sopenharmony_ci spin_unlock(&dev_entry->userptr_spinlock); 189462306a36Sopenharmony_ci} 189562306a36Sopenharmony_ci 189662306a36Sopenharmony_civoid hl_debugfs_add_ctx_mem_hash(struct hl_device *hdev, struct hl_ctx *ctx) 189762306a36Sopenharmony_ci{ 189862306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs; 189962306a36Sopenharmony_ci 190062306a36Sopenharmony_ci mutex_lock(&dev_entry->ctx_mem_hash_mutex); 190162306a36Sopenharmony_ci list_add(&ctx->debugfs_list, &dev_entry->ctx_mem_hash_list); 190262306a36Sopenharmony_ci mutex_unlock(&dev_entry->ctx_mem_hash_mutex); 190362306a36Sopenharmony_ci} 190462306a36Sopenharmony_ci 190562306a36Sopenharmony_civoid hl_debugfs_remove_ctx_mem_hash(struct hl_device *hdev, struct hl_ctx *ctx) 190662306a36Sopenharmony_ci{ 190762306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs; 190862306a36Sopenharmony_ci 190962306a36Sopenharmony_ci mutex_lock(&dev_entry->ctx_mem_hash_mutex); 191062306a36Sopenharmony_ci list_del(&ctx->debugfs_list); 191162306a36Sopenharmony_ci mutex_unlock(&dev_entry->ctx_mem_hash_mutex); 191262306a36Sopenharmony_ci} 191362306a36Sopenharmony_ci 191462306a36Sopenharmony_ci/** 191562306a36Sopenharmony_ci * hl_debugfs_set_state_dump - register state dump making it accessible via 191662306a36Sopenharmony_ci * debugfs 191762306a36Sopenharmony_ci * @hdev: pointer to the device structure 191862306a36Sopenharmony_ci * @data: the actual dump data 191962306a36Sopenharmony_ci * @length: the length of the data 192062306a36Sopenharmony_ci */ 192162306a36Sopenharmony_civoid hl_debugfs_set_state_dump(struct hl_device *hdev, char *data, 192262306a36Sopenharmony_ci unsigned long length) 192362306a36Sopenharmony_ci{ 192462306a36Sopenharmony_ci struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs; 192562306a36Sopenharmony_ci 192662306a36Sopenharmony_ci down_write(&dev_entry->state_dump_sem); 192762306a36Sopenharmony_ci 192862306a36Sopenharmony_ci dev_entry->state_dump_head = (dev_entry->state_dump_head + 1) % 192962306a36Sopenharmony_ci ARRAY_SIZE(dev_entry->state_dump); 193062306a36Sopenharmony_ci vfree(dev_entry->state_dump[dev_entry->state_dump_head]); 193162306a36Sopenharmony_ci dev_entry->state_dump[dev_entry->state_dump_head] = data; 193262306a36Sopenharmony_ci 193362306a36Sopenharmony_ci up_write(&dev_entry->state_dump_sem); 193462306a36Sopenharmony_ci} 193562306a36Sopenharmony_ci 193662306a36Sopenharmony_civoid __init hl_debugfs_init(void) 193762306a36Sopenharmony_ci{ 193862306a36Sopenharmony_ci hl_debug_root = debugfs_create_dir("habanalabs", NULL); 193962306a36Sopenharmony_ci} 194062306a36Sopenharmony_ci 194162306a36Sopenharmony_civoid hl_debugfs_fini(void) 194262306a36Sopenharmony_ci{ 194362306a36Sopenharmony_ci debugfs_remove_recursive(hl_debug_root); 194462306a36Sopenharmony_ci} 1945