]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/xe/pf: Expose VF control operations over debugfs
authorMichal Wajdeczko <michal.wajdeczko@intel.com>
Tue, 30 Sep 2025 23:35:21 +0000 (01:35 +0200)
committerMichal Wajdeczko <michal.wajdeczko@intel.com>
Thu, 2 Oct 2025 21:58:31 +0000 (23:58 +0200)
To allow the user to control the activity of individual VFs,
expose basic VF control operations (pause, resume, stop, reset)
over the debugfs as write-only files:

  /sys/kernel/debug/dri/BDF/sriov/
  ├── vf1
  │   ├── pause
  │   ├── reset
  │   ├── resume
  │   ├── stop
  │   :
  ├── vf2
  :   :

Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Reviewed-by: Michał Winiarski <michal.winiarski@intel.com>
Link: https://lore.kernel.org/r/20250930233525.201263-4-michal.wajdeczko@intel.com
drivers/gpu/drm/xe/xe_sriov_pf_debugfs.c

index 2ab0b1f4818ade8fa997239897c66782e5ef7c78..97636ed86fb8bb1d057431c430fb8911f0631208 100644 (file)
@@ -8,13 +8,41 @@
 
 #include "xe_device.h"
 #include "xe_device_types.h"
+#include "xe_pm.h"
 #include "xe_sriov_pf.h"
+#include "xe_sriov_pf_control.h"
 #include "xe_sriov_pf_debugfs.h"
 #include "xe_sriov_pf_helpers.h"
 #include "xe_sriov_pf_service.h"
 #include "xe_sriov_printk.h"
 #include "xe_tile_sriov_pf_debugfs.h"
 
+/*
+ *      /sys/kernel/debug/dri/BDF/
+ *      ├── sriov                # d_inode->i_private = (xe_device*)
+ *      │   ├── pf             # d_inode->i_private = (xe_device*)
+ *      │   ├── vf1            # d_inode->i_private = VFID(1)
+ *      :   :
+ *      │   ├── vfN            # d_inode->i_private = VFID(N)
+ */
+
+static void *extract_priv(struct dentry *d)
+{
+       return d->d_inode->i_private;
+}
+
+static struct xe_device *extract_xe(struct dentry *d)
+{
+       return extract_priv(d->d_parent);
+}
+
+static unsigned int extract_vfid(struct dentry *d)
+{
+       void *p = extract_priv(d);
+
+       return p == extract_xe(d) ? PFID : (uintptr_t)p;
+}
+
 static int simple_show(struct seq_file *m, void *data)
 {
        struct drm_printer p = drm_seq_file_printer(m);
@@ -39,6 +67,70 @@ static void pf_populate_pf(struct xe_device *xe, struct dentry *pfdent)
        drm_debugfs_create_files(debugfs_list, ARRAY_SIZE(debugfs_list), pfdent, minor);
 }
 
+/*
+ *      /sys/kernel/debug/dri/BDF/
+ *      ├── sriov
+ *      │   ├── vf1
+ *      │   │   ├── pause
+ *      │   │   ├── reset
+ *      │   │   ├── resume
+ *      │   │   ├── stop
+ *      │   │   :
+ *      │   ├── vf2
+ *      │   │   ├── ...
+ */
+
+static ssize_t from_file_write_to_vf_call(struct file *file, const char __user *userbuf,
+                                         size_t count, loff_t *ppos,
+                                         int (*call)(struct xe_device *, unsigned int))
+{
+       struct dentry *dent = file_dentry(file)->d_parent;
+       struct xe_device *xe = extract_xe(dent);
+       unsigned int vfid = extract_vfid(dent);
+       bool yes;
+       int ret;
+
+       if (*ppos)
+               return -EINVAL;
+       ret = kstrtobool_from_user(userbuf, count, &yes);
+       if (ret < 0)
+               return ret;
+       if (yes) {
+               xe_pm_runtime_get(xe);
+               ret = call(xe, vfid);
+               xe_pm_runtime_put(xe);
+       }
+       if (ret < 0)
+               return ret;
+       return count;
+}
+
+#define DEFINE_VF_CONTROL_ATTRIBUTE(OP)                                                \
+static int OP##_show(struct seq_file *s, void *unused)                         \
+{                                                                              \
+       return 0;                                                               \
+}                                                                              \
+static ssize_t OP##_write(struct file *file, const char __user *userbuf,       \
+                         size_t count, loff_t *ppos)                           \
+{                                                                              \
+       return from_file_write_to_vf_call(file, userbuf, count, ppos,           \
+                                         xe_sriov_pf_control_##OP);            \
+}                                                                              \
+DEFINE_SHOW_STORE_ATTRIBUTE(OP)
+
+DEFINE_VF_CONTROL_ATTRIBUTE(pause_vf);
+DEFINE_VF_CONTROL_ATTRIBUTE(resume_vf);
+DEFINE_VF_CONTROL_ATTRIBUTE(stop_vf);
+DEFINE_VF_CONTROL_ATTRIBUTE(reset_vf);
+
+static void pf_populate_vf(struct xe_device *xe, struct dentry *vfdent)
+{
+       debugfs_create_file("pause", 0200, vfdent, xe, &pause_vf_fops);
+       debugfs_create_file("resume", 0200, vfdent, xe, &resume_vf_fops);
+       debugfs_create_file("stop", 0200, vfdent, xe, &stop_vf_fops);
+       debugfs_create_file("reset", 0200, vfdent, xe, &reset_vf_fops);
+}
+
 static void pf_populate_with_tiles(struct xe_device *xe, struct dentry *dent, unsigned int vfid)
 {
        struct xe_tile *tile;
@@ -103,6 +195,7 @@ void xe_sriov_pf_debugfs_register(struct xe_device *xe, struct dentry *root)
                        return;
                vfdent->d_inode->i_private = (void *)(uintptr_t)VFID(n);
 
+               pf_populate_vf(xe, vfdent);
                pf_populate_with_tiles(xe, vfdent, VFID(n));
        }
 }