]>
Commit | Line | Data |
---|---|---|
c2164773 OG |
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 | ||
19 | static struct dentry *hl_debug_root; | |
20 | ||
21 | static 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)) | |
4398e705 | 28 | return -EBUSY; |
c2164773 OG |
29 | |
30 | memset(&pkt, 0, sizeof(pkt)); | |
31 | ||
8c844879 OG |
32 | pkt.ctl = __cpu_to_le32(ARMCP_PACKET_I2C_RD << |
33 | ARMCP_PKT_CTL_OPCODE_SHIFT); | |
c2164773 OG |
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 | ||
47 | static 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)) | |
4398e705 | 54 | return -EBUSY; |
c2164773 OG |
55 | |
56 | memset(&pkt, 0, sizeof(pkt)); | |
57 | ||
8c844879 OG |
58 | pkt.ctl = __cpu_to_le32(ARMCP_PACKET_I2C_WR << |
59 | ARMCP_PKT_CTL_OPCODE_SHIFT); | |
c2164773 OG |
60 | pkt.i2c_bus = i2c_bus; |
61 | pkt.i2c_addr = i2c_addr; | |
62 | pkt.i2c_reg = i2c_reg; | |
8c844879 | 63 | pkt.value = __cpu_to_le64(val); |
c2164773 OG |
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 | ||
74 | static 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 | ||
8c844879 OG |
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); | |
c2164773 OG |
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 | ||
96 | static 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 | ||
127 | static 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 | ||
158 | static 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 | ||
193 | static 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 | ||
224 | static 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; | |
bfb1ce12 | 235 | u64 j; |
c2164773 OG |
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, | |
bfb1ce12 | 264 | " 0x%-14llx %-10llu %-4u\n", |
c2164773 OG |
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"); | |
bfb1ce12 | 286 | for (j = 0 ; j < phys_pg_pack->npages ; j++) { |
c2164773 | 287 | seq_printf(s, " 0x%-14llx\n", |
bfb1ce12 | 288 | phys_pg_pack->pages[j]); |
c2164773 OG |
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 */ | |
304 | static 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 | ||
310 | static 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 | ||
317 | static 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 | ||
324 | static 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 | ||
331 | static 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 | ||
338 | static 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 | ||
345 | static 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 | ||
353 | static 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 = hdev->user_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 (!ctx) { | |
371 | dev_err(hdev->dev, "no ctx available\n"); | |
372 | return 0; | |
373 | } | |
374 | ||
375 | mutex_lock(&ctx->mmu_lock); | |
376 | ||
377 | /* the following lookup is copied from unmap() in mmu.c */ | |
378 | ||
379 | hop0_addr = get_hop0_addr(ctx); | |
380 | hop0_pte_addr = get_hop0_pte_addr(ctx, hop0_addr, virt_addr); | |
381 | hop0_pte = hdev->asic_funcs->read_pte(hdev, hop0_pte_addr); | |
382 | hop1_addr = get_next_hop_addr(hop0_pte); | |
383 | ||
384 | if (hop1_addr == ULLONG_MAX) | |
385 | goto not_mapped; | |
386 | ||
387 | hop1_pte_addr = get_hop1_pte_addr(ctx, hop1_addr, virt_addr); | |
388 | hop1_pte = hdev->asic_funcs->read_pte(hdev, hop1_pte_addr); | |
389 | hop2_addr = get_next_hop_addr(hop1_pte); | |
390 | ||
391 | if (hop2_addr == ULLONG_MAX) | |
392 | goto not_mapped; | |
393 | ||
394 | hop2_pte_addr = get_hop2_pte_addr(ctx, hop2_addr, virt_addr); | |
395 | hop2_pte = hdev->asic_funcs->read_pte(hdev, hop2_pte_addr); | |
396 | hop3_addr = get_next_hop_addr(hop2_pte); | |
397 | ||
398 | if (hop3_addr == ULLONG_MAX) | |
399 | goto not_mapped; | |
400 | ||
401 | hop3_pte_addr = get_hop3_pte_addr(ctx, hop3_addr, virt_addr); | |
402 | hop3_pte = hdev->asic_funcs->read_pte(hdev, hop3_pte_addr); | |
403 | ||
404 | if (!(hop3_pte & LAST_MASK)) { | |
405 | hop4_addr = get_next_hop_addr(hop3_pte); | |
406 | ||
407 | if (hop4_addr == ULLONG_MAX) | |
408 | goto not_mapped; | |
409 | ||
410 | hop4_pte_addr = get_hop4_pte_addr(ctx, hop4_addr, virt_addr); | |
411 | hop4_pte = hdev->asic_funcs->read_pte(hdev, hop4_pte_addr); | |
412 | if (!(hop4_pte & PAGE_PRESENT_MASK)) | |
413 | goto not_mapped; | |
414 | } else { | |
415 | if (!(hop3_pte & PAGE_PRESENT_MASK)) | |
416 | goto not_mapped; | |
417 | } | |
418 | ||
419 | seq_printf(s, "asid: %u, virt_addr: 0x%llx\n", | |
420 | dev_entry->mmu_asid, dev_entry->mmu_addr); | |
421 | ||
422 | seq_printf(s, "hop0_addr: 0x%llx\n", hop0_addr); | |
423 | seq_printf(s, "hop0_pte_addr: 0x%llx\n", hop0_pte_addr); | |
424 | seq_printf(s, "hop0_pte: 0x%llx\n", hop0_pte); | |
425 | ||
426 | seq_printf(s, "hop1_addr: 0x%llx\n", hop1_addr); | |
427 | seq_printf(s, "hop1_pte_addr: 0x%llx\n", hop1_pte_addr); | |
428 | seq_printf(s, "hop1_pte: 0x%llx\n", hop1_pte); | |
429 | ||
430 | seq_printf(s, "hop2_addr: 0x%llx\n", hop2_addr); | |
431 | seq_printf(s, "hop2_pte_addr: 0x%llx\n", hop2_pte_addr); | |
432 | seq_printf(s, "hop2_pte: 0x%llx\n", hop2_pte); | |
433 | ||
434 | seq_printf(s, "hop3_addr: 0x%llx\n", hop3_addr); | |
435 | seq_printf(s, "hop3_pte_addr: 0x%llx\n", hop3_pte_addr); | |
436 | seq_printf(s, "hop3_pte: 0x%llx\n", hop3_pte); | |
437 | ||
438 | if (!(hop3_pte & LAST_MASK)) { | |
439 | seq_printf(s, "hop4_addr: 0x%llx\n", hop4_addr); | |
440 | seq_printf(s, "hop4_pte_addr: 0x%llx\n", hop4_pte_addr); | |
441 | seq_printf(s, "hop4_pte: 0x%llx\n", hop4_pte); | |
442 | } | |
443 | ||
444 | goto out; | |
445 | ||
446 | not_mapped: | |
447 | dev_err(hdev->dev, "virt addr 0x%llx is not mapped to phys addr\n", | |
448 | virt_addr); | |
449 | out: | |
450 | mutex_unlock(&ctx->mmu_lock); | |
451 | ||
452 | return 0; | |
453 | } | |
454 | ||
455 | static ssize_t mmu_write(struct file *file, const char __user *buf, | |
456 | size_t count, loff_t *f_pos) | |
457 | { | |
458 | struct seq_file *s = file->private_data; | |
459 | struct hl_debugfs_entry *entry = s->private; | |
460 | struct hl_dbg_device_entry *dev_entry = entry->dev_entry; | |
461 | struct hl_device *hdev = dev_entry->hdev; | |
8438846c | 462 | char kbuf[MMU_KBUF_SIZE]; |
c2164773 OG |
463 | char *c; |
464 | ssize_t rc; | |
465 | ||
466 | if (!hdev->mmu_enable) | |
467 | return count; | |
468 | ||
8438846c JH |
469 | if (count > sizeof(kbuf) - 1) |
470 | goto err; | |
c2164773 OG |
471 | if (copy_from_user(kbuf, buf, count)) |
472 | goto err; | |
8438846c | 473 | kbuf[count] = 0; |
c2164773 OG |
474 | |
475 | c = strchr(kbuf, ' '); | |
476 | if (!c) | |
477 | goto err; | |
8438846c | 478 | *c = '\0'; |
c2164773 | 479 | |
8438846c | 480 | rc = kstrtouint(kbuf, 10, &dev_entry->mmu_asid); |
c2164773 OG |
481 | if (rc) |
482 | goto err; | |
483 | ||
8438846c | 484 | if (strncmp(c+1, "0x", 2)) |
c2164773 | 485 | goto err; |
8438846c | 486 | rc = kstrtoull(c+3, 16, &dev_entry->mmu_addr); |
c2164773 OG |
487 | if (rc) |
488 | goto err; | |
489 | ||
490 | return count; | |
491 | ||
492 | err: | |
493 | dev_err(hdev->dev, "usage: echo <asid> <0xaddr> > mmu\n"); | |
494 | ||
495 | return -EINVAL; | |
496 | } | |
497 | ||
d75bcf3e TT |
498 | static int device_va_to_pa(struct hl_device *hdev, u64 virt_addr, |
499 | u64 *phys_addr) | |
500 | { | |
501 | struct hl_ctx *ctx = hdev->user_ctx; | |
502 | u64 hop_addr, hop_pte_addr, hop_pte; | |
e4c814aa | 503 | u64 offset_mask = HOP4_MASK | OFFSET_MASK; |
d75bcf3e TT |
504 | int rc = 0; |
505 | ||
506 | if (!ctx) { | |
507 | dev_err(hdev->dev, "no ctx available\n"); | |
508 | return -EINVAL; | |
509 | } | |
510 | ||
511 | mutex_lock(&ctx->mmu_lock); | |
512 | ||
513 | /* hop 0 */ | |
514 | hop_addr = get_hop0_addr(ctx); | |
515 | hop_pte_addr = get_hop0_pte_addr(ctx, hop_addr, virt_addr); | |
516 | hop_pte = hdev->asic_funcs->read_pte(hdev, hop_pte_addr); | |
517 | ||
518 | /* hop 1 */ | |
519 | hop_addr = get_next_hop_addr(hop_pte); | |
520 | if (hop_addr == ULLONG_MAX) | |
521 | goto not_mapped; | |
522 | hop_pte_addr = get_hop1_pte_addr(ctx, hop_addr, virt_addr); | |
523 | hop_pte = hdev->asic_funcs->read_pte(hdev, hop_pte_addr); | |
524 | ||
525 | /* hop 2 */ | |
526 | hop_addr = get_next_hop_addr(hop_pte); | |
527 | if (hop_addr == ULLONG_MAX) | |
528 | goto not_mapped; | |
529 | hop_pte_addr = get_hop2_pte_addr(ctx, hop_addr, virt_addr); | |
530 | hop_pte = hdev->asic_funcs->read_pte(hdev, hop_pte_addr); | |
531 | ||
532 | /* hop 3 */ | |
533 | hop_addr = get_next_hop_addr(hop_pte); | |
534 | if (hop_addr == ULLONG_MAX) | |
535 | goto not_mapped; | |
536 | hop_pte_addr = get_hop3_pte_addr(ctx, hop_addr, virt_addr); | |
537 | hop_pte = hdev->asic_funcs->read_pte(hdev, hop_pte_addr); | |
538 | ||
539 | if (!(hop_pte & LAST_MASK)) { | |
540 | /* hop 4 */ | |
541 | hop_addr = get_next_hop_addr(hop_pte); | |
542 | if (hop_addr == ULLONG_MAX) | |
543 | goto not_mapped; | |
544 | hop_pte_addr = get_hop4_pte_addr(ctx, hop_addr, virt_addr); | |
545 | hop_pte = hdev->asic_funcs->read_pte(hdev, hop_pte_addr); | |
e4c814aa TT |
546 | |
547 | offset_mask = OFFSET_MASK; | |
d75bcf3e TT |
548 | } |
549 | ||
550 | if (!(hop_pte & PAGE_PRESENT_MASK)) | |
551 | goto not_mapped; | |
552 | ||
e4c814aa | 553 | *phys_addr = (hop_pte & ~offset_mask) | (virt_addr & offset_mask); |
d75bcf3e TT |
554 | |
555 | goto out; | |
556 | ||
557 | not_mapped: | |
558 | dev_err(hdev->dev, "virt addr 0x%llx is not mapped to phys addr\n", | |
559 | virt_addr); | |
560 | rc = -EINVAL; | |
561 | out: | |
562 | mutex_unlock(&ctx->mmu_lock); | |
563 | return rc; | |
564 | } | |
565 | ||
c2164773 OG |
566 | static ssize_t hl_data_read32(struct file *f, char __user *buf, |
567 | size_t count, loff_t *ppos) | |
568 | { | |
569 | struct hl_dbg_device_entry *entry = file_inode(f)->i_private; | |
570 | struct hl_device *hdev = entry->hdev; | |
d75bcf3e | 571 | struct asic_fixed_properties *prop = &hdev->asic_prop; |
c2164773 | 572 | char tmp_buf[32]; |
d75bcf3e | 573 | u64 addr = entry->addr; |
c2164773 OG |
574 | u32 val; |
575 | ssize_t rc; | |
576 | ||
577 | if (*ppos) | |
578 | return 0; | |
579 | ||
d75bcf3e TT |
580 | if (addr >= prop->va_space_dram_start_address && |
581 | addr < prop->va_space_dram_end_address && | |
582 | hdev->mmu_enable && | |
583 | hdev->dram_supports_virtual_memory) { | |
584 | rc = device_va_to_pa(hdev, entry->addr, &addr); | |
585 | if (rc) | |
586 | return rc; | |
587 | } | |
588 | ||
589 | rc = hdev->asic_funcs->debugfs_read32(hdev, addr, &val); | |
c2164773 | 590 | if (rc) { |
d75bcf3e | 591 | dev_err(hdev->dev, "Failed to read from 0x%010llx\n", addr); |
c2164773 OG |
592 | return rc; |
593 | } | |
594 | ||
595 | sprintf(tmp_buf, "0x%08x\n", val); | |
8438846c JH |
596 | return simple_read_from_buffer(buf, count, ppos, tmp_buf, |
597 | strlen(tmp_buf)); | |
c2164773 OG |
598 | } |
599 | ||
600 | static ssize_t hl_data_write32(struct file *f, const char __user *buf, | |
601 | size_t count, loff_t *ppos) | |
602 | { | |
603 | struct hl_dbg_device_entry *entry = file_inode(f)->i_private; | |
604 | struct hl_device *hdev = entry->hdev; | |
d75bcf3e TT |
605 | struct asic_fixed_properties *prop = &hdev->asic_prop; |
606 | u64 addr = entry->addr; | |
c2164773 OG |
607 | u32 value; |
608 | ssize_t rc; | |
609 | ||
610 | rc = kstrtouint_from_user(buf, count, 16, &value); | |
611 | if (rc) | |
612 | return rc; | |
613 | ||
d75bcf3e TT |
614 | if (addr >= prop->va_space_dram_start_address && |
615 | addr < prop->va_space_dram_end_address && | |
616 | hdev->mmu_enable && | |
617 | hdev->dram_supports_virtual_memory) { | |
618 | rc = device_va_to_pa(hdev, entry->addr, &addr); | |
619 | if (rc) | |
620 | return rc; | |
621 | } | |
622 | ||
623 | rc = hdev->asic_funcs->debugfs_write32(hdev, addr, value); | |
c2164773 OG |
624 | if (rc) { |
625 | dev_err(hdev->dev, "Failed to write 0x%08x to 0x%010llx\n", | |
d75bcf3e | 626 | value, addr); |
c2164773 OG |
627 | return rc; |
628 | } | |
629 | ||
630 | return count; | |
631 | } | |
632 | ||
633 | static ssize_t hl_get_power_state(struct file *f, char __user *buf, | |
634 | size_t count, loff_t *ppos) | |
635 | { | |
636 | struct hl_dbg_device_entry *entry = file_inode(f)->i_private; | |
637 | struct hl_device *hdev = entry->hdev; | |
638 | char tmp_buf[200]; | |
c2164773 OG |
639 | int i; |
640 | ||
641 | if (*ppos) | |
642 | return 0; | |
643 | ||
644 | if (hdev->pdev->current_state == PCI_D0) | |
645 | i = 1; | |
646 | else if (hdev->pdev->current_state == PCI_D3hot) | |
647 | i = 2; | |
648 | else | |
649 | i = 3; | |
650 | ||
651 | sprintf(tmp_buf, | |
652 | "current power state: %d\n1 - D0\n2 - D3hot\n3 - Unknown\n", i); | |
8438846c JH |
653 | return simple_read_from_buffer(buf, count, ppos, tmp_buf, |
654 | strlen(tmp_buf)); | |
c2164773 OG |
655 | } |
656 | ||
657 | static ssize_t hl_set_power_state(struct file *f, const char __user *buf, | |
658 | size_t count, loff_t *ppos) | |
659 | { | |
660 | struct hl_dbg_device_entry *entry = file_inode(f)->i_private; | |
661 | struct hl_device *hdev = entry->hdev; | |
662 | u32 value; | |
663 | ssize_t rc; | |
664 | ||
665 | rc = kstrtouint_from_user(buf, count, 10, &value); | |
666 | if (rc) | |
667 | return rc; | |
668 | ||
669 | if (value == 1) { | |
670 | pci_set_power_state(hdev->pdev, PCI_D0); | |
671 | pci_restore_state(hdev->pdev); | |
672 | rc = pci_enable_device(hdev->pdev); | |
673 | } else if (value == 2) { | |
674 | pci_save_state(hdev->pdev); | |
675 | pci_disable_device(hdev->pdev); | |
676 | pci_set_power_state(hdev->pdev, PCI_D3hot); | |
677 | } else { | |
678 | dev_dbg(hdev->dev, "invalid power state value %u\n", value); | |
679 | return -EINVAL; | |
680 | } | |
681 | ||
682 | return count; | |
683 | } | |
684 | ||
685 | static ssize_t hl_i2c_data_read(struct file *f, char __user *buf, | |
686 | size_t count, loff_t *ppos) | |
687 | { | |
688 | struct hl_dbg_device_entry *entry = file_inode(f)->i_private; | |
689 | struct hl_device *hdev = entry->hdev; | |
690 | char tmp_buf[32]; | |
691 | u32 val; | |
692 | ssize_t rc; | |
693 | ||
694 | if (*ppos) | |
695 | return 0; | |
696 | ||
697 | rc = hl_debugfs_i2c_read(hdev, entry->i2c_bus, entry->i2c_addr, | |
698 | entry->i2c_reg, &val); | |
699 | if (rc) { | |
700 | dev_err(hdev->dev, | |
701 | "Failed to read from I2C bus %d, addr %d, reg %d\n", | |
702 | entry->i2c_bus, entry->i2c_addr, entry->i2c_reg); | |
703 | return rc; | |
704 | } | |
705 | ||
706 | sprintf(tmp_buf, "0x%02x\n", val); | |
8438846c JH |
707 | rc = simple_read_from_buffer(buf, count, ppos, tmp_buf, |
708 | strlen(tmp_buf)); | |
c2164773 OG |
709 | |
710 | return rc; | |
711 | } | |
712 | ||
713 | static ssize_t hl_i2c_data_write(struct file *f, const char __user *buf, | |
714 | size_t count, loff_t *ppos) | |
715 | { | |
716 | struct hl_dbg_device_entry *entry = file_inode(f)->i_private; | |
717 | struct hl_device *hdev = entry->hdev; | |
718 | u32 value; | |
719 | ssize_t rc; | |
720 | ||
721 | rc = kstrtouint_from_user(buf, count, 16, &value); | |
722 | if (rc) | |
723 | return rc; | |
724 | ||
725 | rc = hl_debugfs_i2c_write(hdev, entry->i2c_bus, entry->i2c_addr, | |
726 | entry->i2c_reg, value); | |
727 | if (rc) { | |
728 | dev_err(hdev->dev, | |
729 | "Failed to write 0x%02x to I2C bus %d, addr %d, reg %d\n", | |
730 | value, entry->i2c_bus, entry->i2c_addr, entry->i2c_reg); | |
731 | return rc; | |
732 | } | |
733 | ||
734 | return count; | |
735 | } | |
736 | ||
737 | static ssize_t hl_led0_write(struct file *f, const char __user *buf, | |
738 | size_t count, loff_t *ppos) | |
739 | { | |
740 | struct hl_dbg_device_entry *entry = file_inode(f)->i_private; | |
741 | struct hl_device *hdev = entry->hdev; | |
742 | u32 value; | |
743 | ssize_t rc; | |
744 | ||
745 | rc = kstrtouint_from_user(buf, count, 10, &value); | |
746 | if (rc) | |
747 | return rc; | |
748 | ||
749 | value = value ? 1 : 0; | |
750 | ||
751 | hl_debugfs_led_set(hdev, 0, value); | |
752 | ||
753 | return count; | |
754 | } | |
755 | ||
756 | static ssize_t hl_led1_write(struct file *f, const char __user *buf, | |
757 | size_t count, loff_t *ppos) | |
758 | { | |
759 | struct hl_dbg_device_entry *entry = file_inode(f)->i_private; | |
760 | struct hl_device *hdev = entry->hdev; | |
761 | u32 value; | |
762 | ssize_t rc; | |
763 | ||
764 | rc = kstrtouint_from_user(buf, count, 10, &value); | |
765 | if (rc) | |
766 | return rc; | |
767 | ||
768 | value = value ? 1 : 0; | |
769 | ||
770 | hl_debugfs_led_set(hdev, 1, value); | |
771 | ||
772 | return count; | |
773 | } | |
774 | ||
775 | static ssize_t hl_led2_write(struct file *f, const char __user *buf, | |
776 | size_t count, loff_t *ppos) | |
777 | { | |
778 | struct hl_dbg_device_entry *entry = file_inode(f)->i_private; | |
779 | struct hl_device *hdev = entry->hdev; | |
780 | u32 value; | |
781 | ssize_t rc; | |
782 | ||
783 | rc = kstrtouint_from_user(buf, count, 10, &value); | |
784 | if (rc) | |
785 | return rc; | |
786 | ||
787 | value = value ? 1 : 0; | |
788 | ||
789 | hl_debugfs_led_set(hdev, 2, value); | |
790 | ||
791 | return count; | |
792 | } | |
793 | ||
794 | static ssize_t hl_device_read(struct file *f, char __user *buf, | |
795 | size_t count, loff_t *ppos) | |
796 | { | |
8438846c JH |
797 | static const char *help = |
798 | "Valid values: disable, enable, suspend, resume, cpu_timeout\n"; | |
799 | return simple_read_from_buffer(buf, count, ppos, help, strlen(help)); | |
c2164773 OG |
800 | } |
801 | ||
802 | static ssize_t hl_device_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; | |
8438846c | 807 | char data[30] = {0}; |
c2164773 OG |
808 | |
809 | /* don't allow partial writes */ | |
810 | if (*ppos != 0) | |
811 | return 0; | |
812 | ||
813 | simple_write_to_buffer(data, 29, ppos, buf, count); | |
814 | ||
815 | if (strncmp("disable", data, strlen("disable")) == 0) { | |
816 | hdev->disabled = true; | |
817 | } else if (strncmp("enable", data, strlen("enable")) == 0) { | |
818 | hdev->disabled = false; | |
819 | } else if (strncmp("suspend", data, strlen("suspend")) == 0) { | |
820 | hdev->asic_funcs->suspend(hdev); | |
821 | } else if (strncmp("resume", data, strlen("resume")) == 0) { | |
822 | hdev->asic_funcs->resume(hdev); | |
a28ce422 OG |
823 | } else if (strncmp("cpu_timeout", data, strlen("cpu_timeout")) == 0) { |
824 | hdev->device_cpu_disabled = true; | |
c2164773 OG |
825 | } else { |
826 | dev_err(hdev->dev, | |
a28ce422 | 827 | "Valid values: disable, enable, suspend, resume, cpu_timeout\n"); |
c2164773 OG |
828 | count = -EINVAL; |
829 | } | |
830 | ||
831 | return count; | |
832 | } | |
833 | ||
834 | static const struct file_operations hl_data32b_fops = { | |
835 | .owner = THIS_MODULE, | |
836 | .read = hl_data_read32, | |
837 | .write = hl_data_write32 | |
838 | }; | |
839 | ||
840 | static const struct file_operations hl_i2c_data_fops = { | |
841 | .owner = THIS_MODULE, | |
842 | .read = hl_i2c_data_read, | |
843 | .write = hl_i2c_data_write | |
844 | }; | |
845 | ||
846 | static const struct file_operations hl_power_fops = { | |
847 | .owner = THIS_MODULE, | |
848 | .read = hl_get_power_state, | |
849 | .write = hl_set_power_state | |
850 | }; | |
851 | ||
852 | static const struct file_operations hl_led0_fops = { | |
853 | .owner = THIS_MODULE, | |
854 | .write = hl_led0_write | |
855 | }; | |
856 | ||
857 | static const struct file_operations hl_led1_fops = { | |
858 | .owner = THIS_MODULE, | |
859 | .write = hl_led1_write | |
860 | }; | |
861 | ||
862 | static const struct file_operations hl_led2_fops = { | |
863 | .owner = THIS_MODULE, | |
864 | .write = hl_led2_write | |
865 | }; | |
866 | ||
867 | static const struct file_operations hl_device_fops = { | |
868 | .owner = THIS_MODULE, | |
869 | .read = hl_device_read, | |
870 | .write = hl_device_write | |
871 | }; | |
872 | ||
873 | static const struct hl_info_list hl_debugfs_list[] = { | |
874 | {"command_buffers", command_buffers_show, NULL}, | |
875 | {"command_submission", command_submission_show, NULL}, | |
876 | {"command_submission_jobs", command_submission_jobs_show, NULL}, | |
877 | {"userptr", userptr_show, NULL}, | |
878 | {"vm", vm_show, NULL}, | |
879 | {"mmu", mmu_show, mmu_write}, | |
880 | }; | |
881 | ||
882 | static int hl_debugfs_open(struct inode *inode, struct file *file) | |
883 | { | |
884 | struct hl_debugfs_entry *node = inode->i_private; | |
885 | ||
886 | return single_open(file, node->info_ent->show, node); | |
887 | } | |
888 | ||
889 | static ssize_t hl_debugfs_write(struct file *file, const char __user *buf, | |
890 | size_t count, loff_t *f_pos) | |
891 | { | |
892 | struct hl_debugfs_entry *node = file->f_inode->i_private; | |
893 | ||
894 | if (node->info_ent->write) | |
895 | return node->info_ent->write(file, buf, count, f_pos); | |
896 | else | |
897 | return -EINVAL; | |
898 | ||
899 | } | |
900 | ||
901 | static const struct file_operations hl_debugfs_fops = { | |
902 | .owner = THIS_MODULE, | |
903 | .open = hl_debugfs_open, | |
904 | .read = seq_read, | |
905 | .write = hl_debugfs_write, | |
906 | .llseek = seq_lseek, | |
907 | .release = single_release, | |
908 | }; | |
909 | ||
910 | void hl_debugfs_add_device(struct hl_device *hdev) | |
911 | { | |
912 | struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs; | |
913 | int count = ARRAY_SIZE(hl_debugfs_list); | |
914 | struct hl_debugfs_entry *entry; | |
915 | struct dentry *ent; | |
916 | int i; | |
917 | ||
918 | dev_entry->hdev = hdev; | |
919 | dev_entry->entry_arr = kmalloc_array(count, | |
920 | sizeof(struct hl_debugfs_entry), | |
921 | GFP_KERNEL); | |
922 | if (!dev_entry->entry_arr) | |
923 | return; | |
924 | ||
925 | INIT_LIST_HEAD(&dev_entry->file_list); | |
926 | INIT_LIST_HEAD(&dev_entry->cb_list); | |
927 | INIT_LIST_HEAD(&dev_entry->cs_list); | |
928 | INIT_LIST_HEAD(&dev_entry->cs_job_list); | |
929 | INIT_LIST_HEAD(&dev_entry->userptr_list); | |
930 | INIT_LIST_HEAD(&dev_entry->ctx_mem_hash_list); | |
931 | mutex_init(&dev_entry->file_mutex); | |
932 | spin_lock_init(&dev_entry->cb_spinlock); | |
933 | spin_lock_init(&dev_entry->cs_spinlock); | |
934 | spin_lock_init(&dev_entry->cs_job_spinlock); | |
935 | spin_lock_init(&dev_entry->userptr_spinlock); | |
936 | spin_lock_init(&dev_entry->ctx_mem_hash_spinlock); | |
937 | ||
938 | dev_entry->root = debugfs_create_dir(dev_name(hdev->dev), | |
939 | hl_debug_root); | |
940 | ||
941 | debugfs_create_x64("addr", | |
942 | 0644, | |
943 | dev_entry->root, | |
944 | &dev_entry->addr); | |
945 | ||
946 | debugfs_create_file("data32", | |
947 | 0644, | |
948 | dev_entry->root, | |
949 | dev_entry, | |
950 | &hl_data32b_fops); | |
951 | ||
952 | debugfs_create_file("set_power_state", | |
953 | 0200, | |
954 | dev_entry->root, | |
955 | dev_entry, | |
956 | &hl_power_fops); | |
957 | ||
958 | debugfs_create_u8("i2c_bus", | |
959 | 0644, | |
960 | dev_entry->root, | |
961 | &dev_entry->i2c_bus); | |
962 | ||
963 | debugfs_create_u8("i2c_addr", | |
964 | 0644, | |
965 | dev_entry->root, | |
966 | &dev_entry->i2c_addr); | |
967 | ||
968 | debugfs_create_u8("i2c_reg", | |
969 | 0644, | |
970 | dev_entry->root, | |
971 | &dev_entry->i2c_reg); | |
972 | ||
973 | debugfs_create_file("i2c_data", | |
974 | 0644, | |
975 | dev_entry->root, | |
976 | dev_entry, | |
977 | &hl_i2c_data_fops); | |
978 | ||
979 | debugfs_create_file("led0", | |
980 | 0200, | |
981 | dev_entry->root, | |
982 | dev_entry, | |
983 | &hl_led0_fops); | |
984 | ||
985 | debugfs_create_file("led1", | |
986 | 0200, | |
987 | dev_entry->root, | |
988 | dev_entry, | |
989 | &hl_led1_fops); | |
990 | ||
991 | debugfs_create_file("led2", | |
992 | 0200, | |
993 | dev_entry->root, | |
994 | dev_entry, | |
995 | &hl_led2_fops); | |
996 | ||
997 | debugfs_create_file("device", | |
998 | 0200, | |
999 | dev_entry->root, | |
1000 | dev_entry, | |
1001 | &hl_device_fops); | |
1002 | ||
1003 | for (i = 0, entry = dev_entry->entry_arr ; i < count ; i++, entry++) { | |
1004 | ||
1005 | ent = debugfs_create_file(hl_debugfs_list[i].name, | |
1006 | 0444, | |
1007 | dev_entry->root, | |
1008 | entry, | |
1009 | &hl_debugfs_fops); | |
1010 | entry->dent = ent; | |
1011 | entry->info_ent = &hl_debugfs_list[i]; | |
1012 | entry->dev_entry = dev_entry; | |
1013 | } | |
1014 | } | |
1015 | ||
1016 | void hl_debugfs_remove_device(struct hl_device *hdev) | |
1017 | { | |
1018 | struct hl_dbg_device_entry *entry = &hdev->hl_debugfs; | |
1019 | ||
1020 | debugfs_remove_recursive(entry->root); | |
1021 | ||
1022 | mutex_destroy(&entry->file_mutex); | |
1023 | kfree(entry->entry_arr); | |
1024 | } | |
1025 | ||
1026 | void hl_debugfs_add_file(struct hl_fpriv *hpriv) | |
1027 | { | |
1028 | struct hl_dbg_device_entry *dev_entry = &hpriv->hdev->hl_debugfs; | |
1029 | ||
1030 | mutex_lock(&dev_entry->file_mutex); | |
1031 | list_add(&hpriv->debugfs_list, &dev_entry->file_list); | |
1032 | mutex_unlock(&dev_entry->file_mutex); | |
1033 | } | |
1034 | ||
1035 | void hl_debugfs_remove_file(struct hl_fpriv *hpriv) | |
1036 | { | |
1037 | struct hl_dbg_device_entry *dev_entry = &hpriv->hdev->hl_debugfs; | |
1038 | ||
1039 | mutex_lock(&dev_entry->file_mutex); | |
1040 | list_del(&hpriv->debugfs_list); | |
1041 | mutex_unlock(&dev_entry->file_mutex); | |
1042 | } | |
1043 | ||
1044 | void hl_debugfs_add_cb(struct hl_cb *cb) | |
1045 | { | |
1046 | struct hl_dbg_device_entry *dev_entry = &cb->hdev->hl_debugfs; | |
1047 | ||
1048 | spin_lock(&dev_entry->cb_spinlock); | |
1049 | list_add(&cb->debugfs_list, &dev_entry->cb_list); | |
1050 | spin_unlock(&dev_entry->cb_spinlock); | |
1051 | } | |
1052 | ||
1053 | void hl_debugfs_remove_cb(struct hl_cb *cb) | |
1054 | { | |
1055 | struct hl_dbg_device_entry *dev_entry = &cb->hdev->hl_debugfs; | |
1056 | ||
1057 | spin_lock(&dev_entry->cb_spinlock); | |
1058 | list_del(&cb->debugfs_list); | |
1059 | spin_unlock(&dev_entry->cb_spinlock); | |
1060 | } | |
1061 | ||
1062 | void hl_debugfs_add_cs(struct hl_cs *cs) | |
1063 | { | |
1064 | struct hl_dbg_device_entry *dev_entry = &cs->ctx->hdev->hl_debugfs; | |
1065 | ||
1066 | spin_lock(&dev_entry->cs_spinlock); | |
1067 | list_add(&cs->debugfs_list, &dev_entry->cs_list); | |
1068 | spin_unlock(&dev_entry->cs_spinlock); | |
1069 | } | |
1070 | ||
1071 | void hl_debugfs_remove_cs(struct hl_cs *cs) | |
1072 | { | |
1073 | struct hl_dbg_device_entry *dev_entry = &cs->ctx->hdev->hl_debugfs; | |
1074 | ||
1075 | spin_lock(&dev_entry->cs_spinlock); | |
1076 | list_del(&cs->debugfs_list); | |
1077 | spin_unlock(&dev_entry->cs_spinlock); | |
1078 | } | |
1079 | ||
1080 | void hl_debugfs_add_job(struct hl_device *hdev, struct hl_cs_job *job) | |
1081 | { | |
1082 | struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs; | |
1083 | ||
1084 | spin_lock(&dev_entry->cs_job_spinlock); | |
1085 | list_add(&job->debugfs_list, &dev_entry->cs_job_list); | |
1086 | spin_unlock(&dev_entry->cs_job_spinlock); | |
1087 | } | |
1088 | ||
1089 | void hl_debugfs_remove_job(struct hl_device *hdev, struct hl_cs_job *job) | |
1090 | { | |
1091 | struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs; | |
1092 | ||
1093 | spin_lock(&dev_entry->cs_job_spinlock); | |
1094 | list_del(&job->debugfs_list); | |
1095 | spin_unlock(&dev_entry->cs_job_spinlock); | |
1096 | } | |
1097 | ||
1098 | void hl_debugfs_add_userptr(struct hl_device *hdev, struct hl_userptr *userptr) | |
1099 | { | |
1100 | struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs; | |
1101 | ||
1102 | spin_lock(&dev_entry->userptr_spinlock); | |
1103 | list_add(&userptr->debugfs_list, &dev_entry->userptr_list); | |
1104 | spin_unlock(&dev_entry->userptr_spinlock); | |
1105 | } | |
1106 | ||
1107 | void hl_debugfs_remove_userptr(struct hl_device *hdev, | |
1108 | struct hl_userptr *userptr) | |
1109 | { | |
1110 | struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs; | |
1111 | ||
1112 | spin_lock(&dev_entry->userptr_spinlock); | |
1113 | list_del(&userptr->debugfs_list); | |
1114 | spin_unlock(&dev_entry->userptr_spinlock); | |
1115 | } | |
1116 | ||
1117 | void hl_debugfs_add_ctx_mem_hash(struct hl_device *hdev, struct hl_ctx *ctx) | |
1118 | { | |
1119 | struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs; | |
1120 | ||
1121 | spin_lock(&dev_entry->ctx_mem_hash_spinlock); | |
1122 | list_add(&ctx->debugfs_list, &dev_entry->ctx_mem_hash_list); | |
1123 | spin_unlock(&dev_entry->ctx_mem_hash_spinlock); | |
1124 | } | |
1125 | ||
1126 | void hl_debugfs_remove_ctx_mem_hash(struct hl_device *hdev, struct hl_ctx *ctx) | |
1127 | { | |
1128 | struct hl_dbg_device_entry *dev_entry = &hdev->hl_debugfs; | |
1129 | ||
1130 | spin_lock(&dev_entry->ctx_mem_hash_spinlock); | |
1131 | list_del(&ctx->debugfs_list); | |
1132 | spin_unlock(&dev_entry->ctx_mem_hash_spinlock); | |
1133 | } | |
1134 | ||
1135 | void __init hl_debugfs_init(void) | |
1136 | { | |
1137 | hl_debug_root = debugfs_create_dir("habanalabs", NULL); | |
1138 | } | |
1139 | ||
1140 | void hl_debugfs_fini(void) | |
1141 | { | |
1142 | debugfs_remove_recursive(hl_debug_root); | |
1143 | } |