Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
   1// SPDX-License-Identifier: GPL-2.0
   2
   3/*
   4 * Copyright 2016-2019 HabanaLabs, Ltd.
   5 * All Rights Reserved.
   6 */
   7
   8#include "habanalabs.h"
   9#include "include/hw_ip/mmu/mmu_general.h"
  10
  11#include <linux/pci.h>
  12#include <linux/debugfs.h>
  13#include <linux/uaccess.h>
  14
  15#define MMU_ADDR_BUF_SIZE	40
  16#define MMU_ASID_BUF_SIZE	10
  17#define MMU_KBUF_SIZE		(MMU_ADDR_BUF_SIZE + MMU_ASID_BUF_SIZE)
  18
  19static struct dentry *hl_debug_root;
  20
  21static int hl_debugfs_i2c_read(struct hl_device *hdev, u8 i2c_bus, u8 i2c_addr,
  22				u8 i2c_reg, u32 *val)
  23{
  24	struct armcp_packet pkt;
  25	int rc;
  26
  27	if (hl_device_disabled_or_in_reset(hdev))
  28		return -EBUSY;
  29
  30	memset(&pkt, 0, sizeof(pkt));
  31
  32	pkt.ctl = cpu_to_le32(ARMCP_PACKET_I2C_RD <<
  33				ARMCP_PKT_CTL_OPCODE_SHIFT);
  34	pkt.i2c_bus = i2c_bus;
  35	pkt.i2c_addr = i2c_addr;
  36	pkt.i2c_reg = i2c_reg;
  37
  38	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
  39					HL_DEVICE_TIMEOUT_USEC, (long *) val);
  40
  41	if (rc)
  42		dev_err(hdev->dev, "Failed to read from I2C, error %d\n", rc);
  43
  44	return rc;
  45}
  46
  47static int hl_debugfs_i2c_write(struct hl_device *hdev, u8 i2c_bus, u8 i2c_addr,
  48				u8 i2c_reg, u32 val)
  49{
  50	struct armcp_packet pkt;
  51	int rc;
  52
  53	if (hl_device_disabled_or_in_reset(hdev))
  54		return -EBUSY;
  55
  56	memset(&pkt, 0, sizeof(pkt));
  57
  58	pkt.ctl = cpu_to_le32(ARMCP_PACKET_I2C_WR <<
  59				ARMCP_PKT_CTL_OPCODE_SHIFT);
  60	pkt.i2c_bus = i2c_bus;
  61	pkt.i2c_addr = i2c_addr;
  62	pkt.i2c_reg = i2c_reg;
  63	pkt.value = cpu_to_le64(val);
  64
  65	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
  66					HL_DEVICE_TIMEOUT_USEC, NULL);
  67
  68	if (rc)
  69		dev_err(hdev->dev, "Failed to write to I2C, error %d\n", rc);
  70
  71	return rc;
  72}
  73
  74static void hl_debugfs_led_set(struct hl_device *hdev, u8 led, u8 state)
  75{
  76	struct armcp_packet pkt;
  77	int rc;
  78
  79	if (hl_device_disabled_or_in_reset(hdev))
  80		return;
  81
  82	memset(&pkt, 0, sizeof(pkt));
  83
  84	pkt.ctl = cpu_to_le32(ARMCP_PACKET_LED_SET <<
  85				ARMCP_PKT_CTL_OPCODE_SHIFT);
  86	pkt.led_index = cpu_to_le32(led);
  87	pkt.value = cpu_to_le64(state);
  88
  89	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
  90						HL_DEVICE_TIMEOUT_USEC, NULL);
  91
  92	if (rc)
  93		dev_err(hdev->dev, "Failed to set LED %d, error %d\n", led, rc);
  94}
  95
  96static int command_buffers_show(struct seq_file *s, void *data)
  97{
  98	struct hl_debugfs_entry *entry = s->private;
  99	struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
 100	struct hl_cb *cb;
 101	bool first = true;
 102
 103	spin_lock(&dev_entry->cb_spinlock);
 104
 105	list_for_each_entry(cb, &dev_entry->cb_list, debugfs_list) {
 106		if (first) {
 107			first = false;
 108			seq_puts(s, "\n");
 109			seq_puts(s, " CB ID   CTX ID   CB size    CB RefCnt    mmap?   CS counter\n");
 110			seq_puts(s, "---------------------------------------------------------------\n");
 111		}
 112		seq_printf(s,
 113			"   %03d        %d    0x%08x      %d          %d          %d\n",
 114			cb->id, cb->ctx_id, cb->size,
 115			kref_read(&cb->refcount),
 116			cb->mmap, cb->cs_cnt);
 117	}
 118
 119	spin_unlock(&dev_entry->cb_spinlock);
 120
 121	if (!first)
 122		seq_puts(s, "\n");
 123
 124	return 0;
 125}
 126
 127static int command_submission_show(struct seq_file *s, void *data)
 128{
 129	struct hl_debugfs_entry *entry = s->private;
 130	struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
 131	struct hl_cs *cs;
 132	bool first = true;
 133
 134	spin_lock(&dev_entry->cs_spinlock);
 135
 136	list_for_each_entry(cs, &dev_entry->cs_list, debugfs_list) {
 137		if (first) {
 138			first = false;
 139			seq_puts(s, "\n");
 140			seq_puts(s, " CS ID   CTX ASID   CS RefCnt   Submitted    Completed\n");
 141			seq_puts(s, "------------------------------------------------------\n");
 142		}
 143		seq_printf(s,
 144			"   %llu       %d          %d           %d            %d\n",
 145			cs->sequence, cs->ctx->asid,
 146			kref_read(&cs->refcount),
 147			cs->submitted, cs->completed);
 148	}
 149
 150	spin_unlock(&dev_entry->cs_spinlock);
 151
 152	if (!first)
 153		seq_puts(s, "\n");
 154
 155	return 0;
 156}
 157
 158static int command_submission_jobs_show(struct seq_file *s, void *data)
 159{
 160	struct hl_debugfs_entry *entry = s->private;
 161	struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
 162	struct hl_cs_job *job;
 163	bool first = true;
 164
 165	spin_lock(&dev_entry->cs_job_spinlock);
 166
 167	list_for_each_entry(job, &dev_entry->cs_job_list, debugfs_list) {
 168		if (first) {
 169			first = false;
 170			seq_puts(s, "\n");
 171			seq_puts(s, " JOB ID   CS ID    CTX ASID   H/W Queue\n");
 172			seq_puts(s, "---------------------------------------\n");
 173		}
 174		if (job->cs)
 175			seq_printf(s,
 176				"    %02d       %llu         %d         %d\n",
 177				job->id, job->cs->sequence, job->cs->ctx->asid,
 178				job->hw_queue_id);
 179		else
 180			seq_printf(s,
 181				"    %02d       0         %d         %d\n",
 182				job->id, HL_KERNEL_ASID_ID, job->hw_queue_id);
 183	}
 184
 185	spin_unlock(&dev_entry->cs_job_spinlock);
 186
 187	if (!first)
 188		seq_puts(s, "\n");
 189
 190	return 0;
 191}
 192
 193static int userptr_show(struct seq_file *s, void *data)
 194{
 195	struct hl_debugfs_entry *entry = s->private;
 196	struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
 197	struct hl_userptr *userptr;
 198	char dma_dir[4][30] = {"DMA_BIDIRECTIONAL", "DMA_TO_DEVICE",
 199				"DMA_FROM_DEVICE", "DMA_NONE"};
 200	bool first = true;
 201
 202	spin_lock(&dev_entry->userptr_spinlock);
 203
 204	list_for_each_entry(userptr, &dev_entry->userptr_list, debugfs_list) {
 205		if (first) {
 206			first = false;
 207			seq_puts(s, "\n");
 208			seq_puts(s, " user virtual address     size             dma dir\n");
 209			seq_puts(s, "----------------------------------------------------------\n");
 210		}
 211		seq_printf(s,
 212			"    0x%-14llx      %-10u    %-30s\n",
 213			userptr->addr, userptr->size, dma_dir[userptr->dir]);
 214	}
 215
 216	spin_unlock(&dev_entry->userptr_spinlock);
 217
 218	if (!first)
 219		seq_puts(s, "\n");
 220
 221	return 0;
 222}
 223
 224static int vm_show(struct seq_file *s, void *data)
 225{
 226	struct hl_debugfs_entry *entry = s->private;
 227	struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
 228	struct hl_ctx *ctx;
 229	struct hl_vm *vm;
 230	struct hl_vm_hash_node *hnode;
 231	struct hl_userptr *userptr;
 232	struct hl_vm_phys_pg_pack *phys_pg_pack = NULL;
 233	enum vm_type_t *vm_type;
 234	bool once = true;
 235	u64 j;
 236	int i;
 237
 238	if (!dev_entry->hdev->mmu_enable)
 239		return 0;
 240
 241	spin_lock(&dev_entry->ctx_mem_hash_spinlock);
 242
 243	list_for_each_entry(ctx, &dev_entry->ctx_mem_hash_list, debugfs_list) {
 244		once = false;
 245		seq_puts(s, "\n\n----------------------------------------------------");
 246		seq_puts(s, "\n----------------------------------------------------\n\n");
 247		seq_printf(s, "ctx asid: %u\n", ctx->asid);
 248
 249		seq_puts(s, "\nmappings:\n\n");
 250		seq_puts(s, "    virtual address        size          handle\n");
 251		seq_puts(s, "----------------------------------------------------\n");
 252		mutex_lock(&ctx->mem_hash_lock);
 253		hash_for_each(ctx->mem_hash, i, hnode, node) {
 254			vm_type = hnode->ptr;
 255
 256			if (*vm_type == VM_TYPE_USERPTR) {
 257				userptr = hnode->ptr;
 258				seq_printf(s,
 259					"    0x%-14llx      %-10u\n",
 260					hnode->vaddr, userptr->size);
 261			} else {
 262				phys_pg_pack = hnode->ptr;
 263				seq_printf(s,
 264					"    0x%-14llx      %-10llu       %-4u\n",
 265					hnode->vaddr, phys_pg_pack->total_size,
 266					phys_pg_pack->handle);
 267			}
 268		}
 269		mutex_unlock(&ctx->mem_hash_lock);
 270
 271		vm = &ctx->hdev->vm;
 272		spin_lock(&vm->idr_lock);
 273
 274		if (!idr_is_empty(&vm->phys_pg_pack_handles))
 275			seq_puts(s, "\n\nallocations:\n");
 276
 277		idr_for_each_entry(&vm->phys_pg_pack_handles, phys_pg_pack, i) {
 278			if (phys_pg_pack->asid != ctx->asid)
 279				continue;
 280
 281			seq_printf(s, "\nhandle: %u\n", phys_pg_pack->handle);
 282			seq_printf(s, "page size: %u\n\n",
 283						phys_pg_pack->page_size);
 284			seq_puts(s, "   physical address\n");
 285			seq_puts(s, "---------------------\n");
 286			for (j = 0 ; j < phys_pg_pack->npages ; j++) {
 287				seq_printf(s, "    0x%-14llx\n",
 288						phys_pg_pack->pages[j]);
 289			}
 290		}
 291		spin_unlock(&vm->idr_lock);
 292
 293	}
 294
 295	spin_unlock(&dev_entry->ctx_mem_hash_spinlock);
 296
 297	if (!once)
 298		seq_puts(s, "\n");
 299
 300	return 0;
 301}
 302
 303/* these inline functions are copied from mmu.c */
 304static inline u64 get_hop0_addr(struct hl_ctx *ctx)
 305{
 306	return ctx->hdev->asic_prop.mmu_pgt_addr +
 307			(ctx->asid * ctx->hdev->asic_prop.mmu_hop_table_size);
 308}
 309
 310static inline u64 get_hop0_pte_addr(struct hl_ctx *ctx, u64 hop_addr,
 311		u64 virt_addr)
 312{
 313	return hop_addr + ctx->hdev->asic_prop.mmu_pte_size *
 314			((virt_addr & HOP0_MASK) >> HOP0_SHIFT);
 315}
 316
 317static inline u64 get_hop1_pte_addr(struct hl_ctx *ctx, u64 hop_addr,
 318		u64 virt_addr)
 319{
 320	return hop_addr + ctx->hdev->asic_prop.mmu_pte_size *
 321			((virt_addr & HOP1_MASK) >> HOP1_SHIFT);
 322}
 323
 324static inline u64 get_hop2_pte_addr(struct hl_ctx *ctx, u64 hop_addr,
 325		u64 virt_addr)
 326{
 327	return hop_addr + ctx->hdev->asic_prop.mmu_pte_size *
 328			((virt_addr & HOP2_MASK) >> HOP2_SHIFT);
 329}
 330
 331static inline u64 get_hop3_pte_addr(struct hl_ctx *ctx, u64 hop_addr,
 332		u64 virt_addr)
 333{
 334	return hop_addr + ctx->hdev->asic_prop.mmu_pte_size *
 335			((virt_addr & HOP3_MASK) >> HOP3_SHIFT);
 336}
 337
 338static inline u64 get_hop4_pte_addr(struct hl_ctx *ctx, u64 hop_addr,
 339		u64 virt_addr)
 340{
 341	return hop_addr + ctx->hdev->asic_prop.mmu_pte_size *
 342			((virt_addr & HOP4_MASK) >> HOP4_SHIFT);
 343}
 344
 345static inline u64 get_next_hop_addr(u64 curr_pte)
 346{
 347	if (curr_pte & PAGE_PRESENT_MASK)
 348		return curr_pte & PHYS_ADDR_MASK;
 349	else
 350		return ULLONG_MAX;
 351}
 352
 353static int mmu_show(struct seq_file *s, void *data)
 354{
 355	struct hl_debugfs_entry *entry = s->private;
 356	struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
 357	struct hl_device *hdev = dev_entry->hdev;
 358	struct hl_ctx *ctx;
 359
 360	u64 hop0_addr = 0, hop0_pte_addr = 0, hop0_pte = 0,
 361		hop1_addr = 0, hop1_pte_addr = 0, hop1_pte = 0,
 362		hop2_addr = 0, hop2_pte_addr = 0, hop2_pte = 0,
 363		hop3_addr = 0, hop3_pte_addr = 0, hop3_pte = 0,
 364		hop4_addr = 0, hop4_pte_addr = 0, hop4_pte = 0,
 365		virt_addr = dev_entry->mmu_addr;
 366
 367	if (!hdev->mmu_enable)
 368		return 0;
 369
 370	if (dev_entry->mmu_asid == HL_KERNEL_ASID_ID)
 371		ctx = hdev->kernel_ctx;
 372	else
 373		ctx = hdev->compute_ctx;
 374
 375	if (!ctx) {
 376		dev_err(hdev->dev, "no ctx available\n");
 377		return 0;
 378	}
 379
 380	mutex_lock(&ctx->mmu_lock);
 381
 382	/* the following lookup is copied from unmap() in mmu.c */
 383
 384	hop0_addr = get_hop0_addr(ctx);
 385	hop0_pte_addr = get_hop0_pte_addr(ctx, hop0_addr, virt_addr);
 386	hop0_pte = hdev->asic_funcs->read_pte(hdev, hop0_pte_addr);
 387	hop1_addr = get_next_hop_addr(hop0_pte);
 388
 389	if (hop1_addr == ULLONG_MAX)
 390		goto not_mapped;
 391
 392	hop1_pte_addr = get_hop1_pte_addr(ctx, hop1_addr, virt_addr);
 393	hop1_pte = hdev->asic_funcs->read_pte(hdev, hop1_pte_addr);
 394	hop2_addr = get_next_hop_addr(hop1_pte);
 395
 396	if (hop2_addr == ULLONG_MAX)
 397		goto not_mapped;
 398
 399	hop2_pte_addr = get_hop2_pte_addr(ctx, hop2_addr, virt_addr);
 400	hop2_pte = hdev->asic_funcs->read_pte(hdev, hop2_pte_addr);
 401	hop3_addr = get_next_hop_addr(hop2_pte);
 402
 403	if (hop3_addr == ULLONG_MAX)
 404		goto not_mapped;
 405
 406	hop3_pte_addr = get_hop3_pte_addr(ctx, hop3_addr, virt_addr);
 407	hop3_pte = hdev->asic_funcs->read_pte(hdev, hop3_pte_addr);
 408
 409	if (!(hop3_pte & LAST_MASK)) {
 410		hop4_addr = get_next_hop_addr(hop3_pte);
 411
 412		if (hop4_addr == ULLONG_MAX)
 413			goto not_mapped;
 414
 415		hop4_pte_addr = get_hop4_pte_addr(ctx, hop4_addr, virt_addr);
 416		hop4_pte = hdev->asic_funcs->read_pte(hdev, hop4_pte_addr);
 417		if (!(hop4_pte & PAGE_PRESENT_MASK))
 418			goto not_mapped;
 419	} else {
 420		if (!(hop3_pte & PAGE_PRESENT_MASK))
 421			goto not_mapped;
 422	}
 423
 424	seq_printf(s, "asid: %u, virt_addr: 0x%llx\n",
 425			dev_entry->mmu_asid, dev_entry->mmu_addr);
 426
 427	seq_printf(s, "hop0_addr: 0x%llx\n", hop0_addr);
 428	seq_printf(s, "hop0_pte_addr: 0x%llx\n", hop0_pte_addr);
 429	seq_printf(s, "hop0_pte: 0x%llx\n", hop0_pte);
 430
 431	seq_printf(s, "hop1_addr: 0x%llx\n", hop1_addr);
 432	seq_printf(s, "hop1_pte_addr: 0x%llx\n", hop1_pte_addr);
 433	seq_printf(s, "hop1_pte: 0x%llx\n", hop1_pte);
 434
 435	seq_printf(s, "hop2_addr: 0x%llx\n", hop2_addr);
 436	seq_printf(s, "hop2_pte_addr: 0x%llx\n", hop2_pte_addr);
 437	seq_printf(s, "hop2_pte: 0x%llx\n", hop2_pte);
 438
 439	seq_printf(s, "hop3_addr: 0x%llx\n", hop3_addr);
 440	seq_printf(s, "hop3_pte_addr: 0x%llx\n", hop3_pte_addr);
 441	seq_printf(s, "hop3_pte: 0x%llx\n", hop3_pte);
 442
 443	if (!(hop3_pte & LAST_MASK)) {
 444		seq_printf(s, "hop4_addr: 0x%llx\n", hop4_addr);
 445		seq_printf(s, "hop4_pte_addr: 0x%llx\n", hop4_pte_addr);
 446		seq_printf(s, "hop4_pte: 0x%llx\n", hop4_pte);
 447	}
 448
 449	goto out;
 450
 451not_mapped:
 452	dev_err(hdev->dev, "virt addr 0x%llx is not mapped to phys addr\n",
 453			virt_addr);
 454out:
 455	mutex_unlock(&ctx->mmu_lock);
 456
 457	return 0;
 458}
 459
 460static ssize_t mmu_write(struct file *file, const char __user *buf,
 461		size_t count, loff_t *f_pos)
 462{
 463	struct seq_file *s = file->private_data;
 464	struct hl_debugfs_entry *entry = s->private;
 465	struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
 466	struct hl_device *hdev = dev_entry->hdev;
 467	char kbuf[MMU_KBUF_SIZE];
 468	char *c;
 469	ssize_t rc;
 470
 471	if (!hdev->mmu_enable)
 472		return count;
 473
 474	if (count > sizeof(kbuf) - 1)
 475		goto err;
 476	if (copy_from_user(kbuf, buf, count))
 477		goto err;
 478	kbuf[count] = 0;
 479
 480	c = strchr(kbuf, ' ');
 481	if (!c)
 482		goto err;
 483	*c = '\0';
 484
 485	rc = kstrtouint(kbuf, 10, &dev_entry->mmu_asid);
 486	if (rc)
 487		goto err;
 488
 489	if (strncmp(c+1, "0x", 2))
 490		goto err;
 491	rc = kstrtoull(c+3, 16, &dev_entry->mmu_addr);
 492	if (rc)
 493		goto err;
 494
 495	return count;
 496
 497err:
 498	dev_err(hdev->dev, "usage: echo <asid> <0xaddr> > mmu\n");
 499
 500	return -EINVAL;
 501}
 502
 503static int engines_show(struct seq_file *s, void *data)
 504{
 505	struct hl_debugfs_entry *entry = s->private;
 506	struct hl_dbg_device_entry *dev_entry = entry->dev_entry;
 507	struct hl_device *hdev = dev_entry->hdev;
 508
 509	hdev->asic_funcs->is_device_idle(hdev, NULL, s);
 510
 511	return 0;
 512}
 513
 514static bool hl_is_device_va(struct hl_device *hdev, u64 addr)
 515{
 516	struct asic_fixed_properties *prop = &hdev->asic_prop;
 517
 518	if (!hdev->mmu_enable)
 519		goto out;
 520
 521	if (hdev->dram_supports_virtual_memory &&
 522			addr >= prop->va_space_dram_start_address &&
 523			addr < prop->va_space_dram_end_address)
 524		return true;
 525
 526	if (addr >= prop->va_space_host_start_address &&
 527			addr < prop->va_space_host_end_address)
 528		return true;
 529out:
 530	return false;
 531}
 532
 533static int device_va_to_pa(struct hl_device *hdev, u64 virt_addr,
 534				u64 *phys_addr)
 535{
 536	struct hl_ctx *ctx = hdev->compute_ctx;
 537	u64 hop_addr, hop_pte_addr, hop_pte;
 538	u64 offset_mask = HOP4_MASK | OFFSET_MASK;
 539	int rc = 0;
 540
 541	if (!ctx) {
 542		dev_err(hdev->dev, "no ctx available\n");
 543		return -EINVAL;
 544	}
 545
 546	mutex_lock(&ctx->mmu_lock);
 547
 548	/* hop 0 */
 549	hop_addr = get_hop0_addr(ctx);
 550	hop_pte_addr = get_hop0_pte_addr(ctx, hop_addr, virt_addr);
 551	hop_pte = hdev->asic_funcs->read_pte(hdev, hop_pte_addr);
 552
 553	/* hop 1 */
 554	hop_addr = get_next_hop_addr(hop_pte);
 555	if (hop_addr == ULLONG_MAX)
 556		goto not_mapped;
 557	hop_pte_addr = get_hop1_pte_addr(ctx, hop_addr, virt_addr);
 558	hop_pte = hdev->asic_funcs->read_pte(hdev, hop_pte_addr);
 559
 560	/* hop 2 */
 561	hop_addr = get_next_hop_addr(hop_pte);
 562	if (hop_addr == ULLONG_MAX)
 563		goto not_mapped;
 564	hop_pte_addr = get_hop2_pte_addr(ctx, hop_addr, virt_addr);
 565	hop_pte = hdev->asic_funcs->read_pte(hdev, hop_pte_addr);
 566
 567	/* hop 3 */
 568	hop_addr = get_next_hop_addr(hop_pte);
 569	if (hop_addr == ULLONG_MAX)
 570		goto not_mapped;
 571	hop_pte_addr = get_hop3_pte_addr(ctx, hop_addr, virt_addr);
 572	hop_pte = hdev->asic_funcs->read_pte(hdev, hop_pte_addr);
 573
 574	if (!(hop_pte & LAST_MASK)) {
 575		/* hop 4 */
 576		hop_addr = get_next_hop_addr(hop_pte);
 577		if (hop_addr == ULLONG_MAX)
 578			goto not_mapped;
 579		hop_pte_addr = get_hop4_pte_addr(ctx, hop_addr, virt_addr);
 580		hop_pte = hdev->asic_funcs->read_pte(hdev, hop_pte_addr);
 581
 582		offset_mask = OFFSET_MASK;
 583	}
 584
 585	if (!(hop_pte & PAGE_PRESENT_MASK))
 586		goto not_mapped;
 587
 588	*phys_addr = (hop_pte & ~offset_mask) | (virt_addr & offset_mask);
 589
 590	goto out;
 591
 592not_mapped:
 593	dev_err(hdev->dev, "virt addr 0x%llx is not mapped to phys addr\n",
 594			virt_addr);
 595	rc = -EINVAL;
 596out:
 597	mutex_unlock(&ctx->mmu_lock);
 598	return rc;
 599}
 600
 601static ssize_t hl_data_read32(struct file *f, char __user *buf,
 602					size_t count, loff_t *ppos)
 603{
 604	struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
 605	struct hl_device *hdev = entry->hdev;
 606	char tmp_buf[32];
 607	u64 addr = entry->addr;
 608	u32 val;
 609	ssize_t rc;
 610
 611	if (*ppos)
 612		return 0;
 613
 614	if (hl_is_device_va(hdev, addr)) {
 615		rc = device_va_to_pa(hdev, addr, &addr);
 616		if (rc)
 617			return rc;
 618	}
 619
 620	rc = hdev->asic_funcs->debugfs_read32(hdev, addr, &val);
 621	if (rc) {
 622		dev_err(hdev->dev, "Failed to read from 0x%010llx\n", addr);
 623		return rc;
 624	}
 625
 626	sprintf(tmp_buf, "0x%08x\n", val);
 627	return simple_read_from_buffer(buf, count, ppos, tmp_buf,
 628			strlen(tmp_buf));
 629}
 630
 631static ssize_t hl_data_write32(struct file *f, const char __user *buf,
 632					size_t count, loff_t *ppos)
 633{
 634	struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
 635	struct hl_device *hdev = entry->hdev;
 636	u64 addr = entry->addr;
 637	u32 value;
 638	ssize_t rc;
 639
 640	rc = kstrtouint_from_user(buf, count, 16, &value);
 641	if (rc)
 642		return rc;
 643
 644	if (hl_is_device_va(hdev, addr)) {
 645		rc = device_va_to_pa(hdev, addr, &addr);
 646		if (rc)
 647			return rc;
 648	}
 649
 650	rc = hdev->asic_funcs->debugfs_write32(hdev, addr, value);
 651	if (rc) {
 652		dev_err(hdev->dev, "Failed to write 0x%08x to 0x%010llx\n",
 653			value, addr);
 654		return rc;
 655	}
 656
 657	return count;
 658}
 659
 660static ssize_t hl_get_power_state(struct file *f, char __user *buf,
 661		size_t count, loff_t *ppos)
 662{
 663	struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
 664	struct hl_device *hdev = entry->hdev;
 665	char tmp_buf[200];
 666	int i;
 667
 668	if (*ppos)
 669		return 0;
 670
 671	if (hdev->pdev->current_state == PCI_D0)
 672		i = 1;
 673	else if (hdev->pdev->current_state == PCI_D3hot)
 674		i = 2;
 675	else
 676		i = 3;
 677
 678	sprintf(tmp_buf,
 679		"current power state: %d\n1 - D0\n2 - D3hot\n3 - Unknown\n", i);
 680	return simple_read_from_buffer(buf, count, ppos, tmp_buf,
 681			strlen(tmp_buf));
 682}
 683
 684static ssize_t hl_set_power_state(struct file *f, const char __user *buf,
 685					size_t count, loff_t *ppos)
 686{
 687	struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
 688	struct hl_device *hdev = entry->hdev;
 689	u32 value;
 690	ssize_t rc;
 691
 692	rc = kstrtouint_from_user(buf, count, 10, &value);
 693	if (rc)
 694		return rc;
 695
 696	if (value == 1) {
 697		pci_set_power_state(hdev->pdev, PCI_D0);
 698		pci_restore_state(hdev->pdev);
 699		rc = pci_enable_device(hdev->pdev);
 700	} else if (value == 2) {
 701		pci_save_state(hdev->pdev);
 702		pci_disable_device(hdev->pdev);
 703		pci_set_power_state(hdev->pdev, PCI_D3hot);
 704	} else {
 705		dev_dbg(hdev->dev, "invalid power state value %u\n", value);
 706		return -EINVAL;
 707	}
 708
 709	return count;
 710}
 711
 712static ssize_t hl_i2c_data_read(struct file *f, char __user *buf,
 713					size_t count, loff_t *ppos)
 714{
 715	struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
 716	struct hl_device *hdev = entry->hdev;
 717	char tmp_buf[32];
 718	u32 val;
 719	ssize_t rc;
 720
 721	if (*ppos)
 722		return 0;
 723
 724	rc = hl_debugfs_i2c_read(hdev, entry->i2c_bus, entry->i2c_addr,
 725			entry->i2c_reg, &val);
 726	if (rc) {
 727		dev_err(hdev->dev,
 728			"Failed to read from I2C bus %d, addr %d, reg %d\n",
 729			entry->i2c_bus, entry->i2c_addr, entry->i2c_reg);
 730		return rc;
 731	}
 732
 733	sprintf(tmp_buf, "0x%02x\n", val);
 734	rc = simple_read_from_buffer(buf, count, ppos, tmp_buf,
 735			strlen(tmp_buf));
 736
 737	return rc;
 738}
 739
 740static ssize_t hl_i2c_data_write(struct file *f, const char __user *buf,
 741					size_t count, loff_t *ppos)
 742{
 743	struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
 744	struct hl_device *hdev = entry->hdev;
 745	u32 value;
 746	ssize_t rc;
 747
 748	rc = kstrtouint_from_user(buf, count, 16, &value);
 749	if (rc)
 750		return rc;
 751
 752	rc = hl_debugfs_i2c_write(hdev, entry->i2c_bus, entry->i2c_addr,
 753			entry->i2c_reg, value);
 754	if (rc) {
 755		dev_err(hdev->dev,
 756			"Failed to write 0x%02x to I2C bus %d, addr %d, reg %d\n",
 757			value, entry->i2c_bus, entry->i2c_addr, entry->i2c_reg);
 758		return rc;
 759	}
 760
 761	return count;
 762}
 763
 764static ssize_t hl_led0_write(struct file *f, const char __user *buf,
 765					size_t count, loff_t *ppos)
 766{
 767	struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
 768	struct hl_device *hdev = entry->hdev;
 769	u32 value;
 770	ssize_t rc;
 771
 772	rc = kstrtouint_from_user(buf, count, 10, &value);
 773	if (rc)
 774		return rc;
 775
 776	value = value ? 1 : 0;
 777
 778	hl_debugfs_led_set(hdev, 0, value);
 779
 780	return count;
 781}
 782
 783static ssize_t hl_led1_write(struct file *f, const char __user *buf,
 784					size_t count, loff_t *ppos)
 785{
 786	struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
 787	struct hl_device *hdev = entry->hdev;
 788	u32 value;
 789	ssize_t rc;
 790
 791	rc = kstrtouint_from_user(buf, count, 10, &value);
 792	if (rc)
 793		return rc;
 794
 795	value = value ? 1 : 0;
 796
 797	hl_debugfs_led_set(hdev, 1, value);
 798
 799	return count;
 800}
 801
 802static ssize_t hl_led2_write(struct file *f, const char __user *buf,
 803					size_t count, loff_t *ppos)
 804{
 805	struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
 806	struct hl_device *hdev = entry->hdev;
 807	u32 value;
 808	ssize_t rc;
 809
 810	rc = kstrtouint_from_user(buf, count, 10, &value);
 811	if (rc)
 812		return rc;
 813
 814	value = value ? 1 : 0;
 815
 816	hl_debugfs_led_set(hdev, 2, value);
 817
 818	return count;
 819}
 820
 821static ssize_t hl_device_read(struct file *f, char __user *buf,
 822					size_t count, loff_t *ppos)
 823{
 824	static const char *help =
 825		"Valid values: disable, enable, suspend, resume, cpu_timeout\n";
 826	return simple_read_from_buffer(buf, count, ppos, help, strlen(help));
 827}
 828
 829static ssize_t hl_device_write(struct file *f, const char __user *buf,
 830				     size_t count, loff_t *ppos)
 831{
 832	struct hl_dbg_device_entry *entry = file_inode(f)->i_private;
 833	struct hl_device *hdev = entry->hdev;
 834	char data[30] = {0};
 835
 836	/* don't allow partial writes */
 837	if (*ppos != 0)
 838		return 0;
 839
 840	simple_write_to_buffer(data, 29, ppos, buf, count);
 841
 842	if (strncmp("disable", data, strlen("disable")) == 0) {
 843		hdev->disabled = true;
 844	} else if (strncmp("enable", data, strlen("enable")) == 0) {
 845		hdev->disabled = false;
 846	} else if (strncmp("suspend", data, strlen("suspend")) == 0) {
 847		hdev->asic_funcs->suspend(hdev);
 848	} else if (strncmp("resume", data, strlen("resume")) == 0) {
 849		hdev->asic_funcs->resume(hdev);
 850	} else if (strncmp("cpu_timeout", data, strlen("cpu_timeout")) == 0) {
 851		hdev->device_cpu_disabled = true;
 852	} else {
 853		dev_err(hdev->dev,
 854			"Valid values: disable, enable, suspend, resume, cpu_timeout\n");
 855		count = -EINVAL;
 856	}
 857
 858	return count;
 859}
 860
 861static const struct file_operations hl_data32b_fops = {
 862	.owner = THIS_MODULE,
 863	.read = hl_data_read32,
 864	.write = hl_data_write32
 865};
 866
 867static const struct file_operations hl_i2c_data_fops = {
 868	.owner = THIS_MODULE,
 869	.read = hl_i2c_data_read,
 870	.write = hl_i2c_data_write
 871};
 872
 873static const struct file_operations hl_power_fops = {
 874	.owner = THIS_MODULE,
 875	.read = hl_get_power_state,
 876	.write = hl_set_power_state
 877};
 878
 879static const struct file_operations hl_led0_fops = {
 880	.owner = THIS_MODULE,
 881	.write = hl_led0_write
 882};
 883
 884static const struct file_operations hl_led1_fops = {
 885	.owner = THIS_MODULE,
 886	.write = hl_led1_write
 887};
 888
 889static const struct file_operations hl_led2_fops = {
 890	.owner = THIS_MODULE,
 891	.write = hl_led2_write
 892};
 893
 894static const struct file_operations hl_device_fops = {
 895	.owner = THIS_MODULE,
 896	.read = hl_device_read,
 897	.write = hl_device_write
 898};
 899
 900static const struct hl_info_list hl_debugfs_list[] = {
 901	{"command_buffers", command_buffers_show, NULL},
 902	{"command_submission", command_submission_show, NULL},
 903	{"command_submission_jobs", command_submission_jobs_show, NULL},
 904	{"userptr", userptr_show, NULL},
 905	{"vm", vm_show, NULL},
 906	{"mmu", mmu_show, mmu_write},
 907	{"engines", engines_show, NULL}
 908};
 909
 910static int hl_debugfs_open(struct inode *inode, struct file *file)
 911{
 912	struct hl_debugfs_entry *node = inode->i_private;
 913
 914	return single_open(file, node->info_ent->show, node);
 915}
 916
 917static ssize_t hl_debugfs_write(struct file *file, const char __user *buf,
 918		size_t count, loff_t *f_pos)
 919{
 920	struct hl_debugfs_entry *node = file->f_inode->i_private;
 921
 922	if (node->info_ent->write)
 923		return node->info_ent->write(file, buf, count, f_pos);
 924	else
 925		return -EINVAL;
 926
 927}
 928
 929static const struct file_operations hl_debugfs_fops = {
 930	.owner = THIS_MODULE,
 931	.open = hl_debugfs_open,
 932	.read = seq_read,
 933	.write = hl_debugfs_write,
 934	.llseek = seq_lseek,
 935	.release = single_release,
 936};
 937
 938void hl_debugfs_add_device(struct hl_device *hdev)
 939{
 940	struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;
 941	int count = ARRAY_SIZE(hl_debugfs_list);
 942	struct hl_debugfs_entry *entry;
 943	struct dentry *ent;
 944	int i;
 945
 946	dev_entry->hdev = hdev;
 947	dev_entry->entry_arr = kmalloc_array(count,
 948					sizeof(struct hl_debugfs_entry),
 949					GFP_KERNEL);
 950	if (!dev_entry->entry_arr)
 951		return;
 952
 953	INIT_LIST_HEAD(&dev_entry->file_list);
 954	INIT_LIST_HEAD(&dev_entry->cb_list);
 955	INIT_LIST_HEAD(&dev_entry->cs_list);
 956	INIT_LIST_HEAD(&dev_entry->cs_job_list);
 957	INIT_LIST_HEAD(&dev_entry->userptr_list);
 958	INIT_LIST_HEAD(&dev_entry->ctx_mem_hash_list);
 959	mutex_init(&dev_entry->file_mutex);
 960	spin_lock_init(&dev_entry->cb_spinlock);
 961	spin_lock_init(&dev_entry->cs_spinlock);
 962	spin_lock_init(&dev_entry->cs_job_spinlock);
 963	spin_lock_init(&dev_entry->userptr_spinlock);
 964	spin_lock_init(&dev_entry->ctx_mem_hash_spinlock);
 965
 966	dev_entry->root = debugfs_create_dir(dev_name(hdev->dev),
 967						hl_debug_root);
 968
 969	debugfs_create_x64("addr",
 970				0644,
 971				dev_entry->root,
 972				&dev_entry->addr);
 973
 974	debugfs_create_file("data32",
 975				0644,
 976				dev_entry->root,
 977				dev_entry,
 978				&hl_data32b_fops);
 979
 980	debugfs_create_file("set_power_state",
 981				0200,
 982				dev_entry->root,
 983				dev_entry,
 984				&hl_power_fops);
 985
 986	debugfs_create_u8("i2c_bus",
 987				0644,
 988				dev_entry->root,
 989				&dev_entry->i2c_bus);
 990
 991	debugfs_create_u8("i2c_addr",
 992				0644,
 993				dev_entry->root,
 994				&dev_entry->i2c_addr);
 995
 996	debugfs_create_u8("i2c_reg",
 997				0644,
 998				dev_entry->root,
 999				&dev_entry->i2c_reg);
1000
1001	debugfs_create_file("i2c_data",
1002				0644,
1003				dev_entry->root,
1004				dev_entry,
1005				&hl_i2c_data_fops);
1006
1007	debugfs_create_file("led0",
1008				0200,
1009				dev_entry->root,
1010				dev_entry,
1011				&hl_led0_fops);
1012
1013	debugfs_create_file("led1",
1014				0200,
1015				dev_entry->root,
1016				dev_entry,
1017				&hl_led1_fops);
1018
1019	debugfs_create_file("led2",
1020				0200,
1021				dev_entry->root,
1022				dev_entry,
1023				&hl_led2_fops);
1024
1025	debugfs_create_file("device",
1026				0200,
1027				dev_entry->root,
1028				dev_entry,
1029				&hl_device_fops);
1030
1031	for (i = 0, entry = dev_entry->entry_arr ; i < count ; i++, entry++) {
1032
1033		ent = debugfs_create_file(hl_debugfs_list[i].name,
1034					0444,
1035					dev_entry->root,
1036					entry,
1037					&hl_debugfs_fops);
1038		entry->dent = ent;
1039		entry->info_ent = &hl_debugfs_list[i];
1040		entry->dev_entry = dev_entry;
1041	}
1042}
1043
1044void hl_debugfs_remove_device(struct hl_device *hdev)
1045{
1046	struct hl_dbg_device_entry *entry = &hdev->hl_debugfs;
1047
1048	debugfs_remove_recursive(entry->root);
1049
1050	mutex_destroy(&entry->file_mutex);
1051	kfree(entry->entry_arr);
1052}
1053
1054void hl_debugfs_add_file(struct hl_fpriv *hpriv)
1055{
1056	struct hl_dbg_device_entry *dev_entry = &hpriv->hdev->hl_debugfs;
1057
1058	mutex_lock(&dev_entry->file_mutex);
1059	list_add(&hpriv->debugfs_list, &dev_entry->file_list);
1060	mutex_unlock(&dev_entry->file_mutex);
1061}
1062
1063void hl_debugfs_remove_file(struct hl_fpriv *hpriv)
1064{
1065	struct hl_dbg_device_entry *dev_entry = &hpriv->hdev->hl_debugfs;
1066
1067	mutex_lock(&dev_entry->file_mutex);
1068	list_del(&hpriv->debugfs_list);
1069	mutex_unlock(&dev_entry->file_mutex);
1070}
1071
1072void hl_debugfs_add_cb(struct hl_cb *cb)
1073{
1074	struct hl_dbg_device_entry *dev_entry = &cb->hdev->hl_debugfs;
1075
1076	spin_lock(&dev_entry->cb_spinlock);
1077	list_add(&cb->debugfs_list, &dev_entry->cb_list);
1078	spin_unlock(&dev_entry->cb_spinlock);
1079}
1080
1081void hl_debugfs_remove_cb(struct hl_cb *cb)
1082{
1083	struct hl_dbg_device_entry *dev_entry = &cb->hdev->hl_debugfs;
1084
1085	spin_lock(&dev_entry->cb_spinlock);
1086	list_del(&cb->debugfs_list);
1087	spin_unlock(&dev_entry->cb_spinlock);
1088}
1089
1090void hl_debugfs_add_cs(struct hl_cs *cs)
1091{
1092	struct hl_dbg_device_entry *dev_entry = &cs->ctx->hdev->hl_debugfs;
1093
1094	spin_lock(&dev_entry->cs_spinlock);
1095	list_add(&cs->debugfs_list, &dev_entry->cs_list);
1096	spin_unlock(&dev_entry->cs_spinlock);
1097}
1098
1099void hl_debugfs_remove_cs(struct hl_cs *cs)
1100{
1101	struct hl_dbg_device_entry *dev_entry = &cs->ctx->hdev->hl_debugfs;
1102
1103	spin_lock(&dev_entry->cs_spinlock);
1104	list_del(&cs->debugfs_list);
1105	spin_unlock(&dev_entry->cs_spinlock);
1106}
1107
1108void hl_debugfs_add_job(struct hl_device *hdev, struct hl_cs_job *job)
1109{
1110	struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;
1111
1112	spin_lock(&dev_entry->cs_job_spinlock);
1113	list_add(&job->debugfs_list, &dev_entry->cs_job_list);
1114	spin_unlock(&dev_entry->cs_job_spinlock);
1115}
1116
1117void hl_debugfs_remove_job(struct hl_device *hdev, struct hl_cs_job *job)
1118{
1119	struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;
1120
1121	spin_lock(&dev_entry->cs_job_spinlock);
1122	list_del(&job->debugfs_list);
1123	spin_unlock(&dev_entry->cs_job_spinlock);
1124}
1125
1126void hl_debugfs_add_userptr(struct hl_device *hdev, struct hl_userptr *userptr)
1127{
1128	struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;
1129
1130	spin_lock(&dev_entry->userptr_spinlock);
1131	list_add(&userptr->debugfs_list, &dev_entry->userptr_list);
1132	spin_unlock(&dev_entry->userptr_spinlock);
1133}
1134
1135void hl_debugfs_remove_userptr(struct hl_device *hdev,
1136				struct hl_userptr *userptr)
1137{
1138	struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;
1139
1140	spin_lock(&dev_entry->userptr_spinlock);
1141	list_del(&userptr->debugfs_list);
1142	spin_unlock(&dev_entry->userptr_spinlock);
1143}
1144
1145void hl_debugfs_add_ctx_mem_hash(struct hl_device *hdev, struct hl_ctx *ctx)
1146{
1147	struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;
1148
1149	spin_lock(&dev_entry->ctx_mem_hash_spinlock);
1150	list_add(&ctx->debugfs_list, &dev_entry->ctx_mem_hash_list);
1151	spin_unlock(&dev_entry->ctx_mem_hash_spinlock);
1152}
1153
1154void hl_debugfs_remove_ctx_mem_hash(struct hl_device *hdev, struct hl_ctx *ctx)
1155{
1156	struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs;
1157
1158	spin_lock(&dev_entry->ctx_mem_hash_spinlock);
1159	list_del(&ctx->debugfs_list);
1160	spin_unlock(&dev_entry->ctx_mem_hash_spinlock);
1161}
1162
1163void __init hl_debugfs_init(void)
1164{
1165	hl_debug_root = debugfs_create_dir("habanalabs", NULL);
1166}
1167
1168void hl_debugfs_fini(void)
1169{
1170	debugfs_remove_recursive(hl_debug_root);
1171}