// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2026, Advanced Micro Devices, Inc. */ #include "amdxdna_cbuf.h" #include "amdxdna_debugfs.h" #include #include #include #include #include #include #define _DBGFS_FOPS(_open, _release, _write) \ { \ .owner = THIS_MODULE, \ .open = _open, \ .read = seq_read, \ .llseek = seq_lseek, \ .release = _release, \ .write = _write, \ } #define AMDXDNA_DBGFS_FOPS(_name, _show, _write) \ static int amdxdna_dbgfs_##_name##_open(struct inode *inode, struct file *file) \ { \ return single_open(file, _show, inode->i_private); \ } \ static int amdxdna_dbgfs_##_name##_release(struct inode *inode, struct file *file) \ { \ return single_release(inode, file); \ } \ static const struct file_operations amdxdna_fops_##_name = \ _DBGFS_FOPS(amdxdna_dbgfs_##_name##_open, amdxdna_dbgfs_##_name##_release, _write) #define AMDXDNA_DBGFS_FILE(_name, _mode) { #_name, &amdxdna_fops_##_name, _mode } #define file_to_xdna(file) (((struct seq_file *)(file)->private_data)->private) static ssize_t amdxdna_carveout_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { struct amdxdna_dev *xdna = file_to_xdna(file); char kbuf[128]; u64 size, addr; char *sep; int ret; if (count == 0 || count >= sizeof(kbuf)) return -EINVAL; if (copy_from_user(kbuf, buf, count)) return -EFAULT; kbuf[count] = '\0'; strim(kbuf); XDNA_DBG(xdna, "Trying to set carveout to %s", kbuf); sep = strchr(kbuf, '@'); if (!sep) return -EINVAL; *sep = '\0'; sep++; ret = kstrtou64(kbuf, 0, &size); if (ret) return ret; ret = kstrtou64(sep, 0, &addr); if (ret) return ret; /* Sanity check the addr and size. */ if (!size) return -EINVAL; if (!IS_ALIGNED(addr, PAGE_SIZE) || !IS_ALIGNED(size, PAGE_SIZE)) return -EINVAL; guard(mutex)(&xdna->dev_lock); ret = amdxdna_carveout_init(xdna, addr, size); if (ret) return ret; return count; } static int amdxdna_carveout_show(struct seq_file *m, void *unused) { struct amdxdna_dev *xdna = m->private; u64 addr, size; guard(mutex)(&xdna->dev_lock); amdxdna_get_carveout_conf(xdna, &addr, &size); seq_printf(m, "0x%llx@0x%llx\n", size, addr); return 0; } /* * Input/output format: @ */ AMDXDNA_DBGFS_FOPS(carveout, amdxdna_carveout_show, amdxdna_carveout_write); static const struct { const char *name; const struct file_operations *fops; umode_t mode; } amdxdna_dbgfs_files[] = { AMDXDNA_DBGFS_FILE(carveout, 0600), }; void amdxdna_debugfs_init(struct amdxdna_dev *xdna) { struct drm_minor *minor = xdna->ddev.accel; int i; /* * It should be okay that debugfs fails to init. * We rely on DRM framework to finish debugfs. */ for (i = 0; i < ARRAY_SIZE(amdxdna_dbgfs_files); i++) { debugfs_create_file(amdxdna_dbgfs_files[i].name, amdxdna_dbgfs_files[i].mode, minor->debugfs_root, xdna, amdxdna_dbgfs_files[i].fops); } }