Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/xe: Add configfs to enable survivability mode

Registers a configfs subsystem called 'xe' that creates a
directory in the mounted configfs directory (/sys/kernel/config)
Userspace can then create the device that has to be configured
under the xe directory

mkdir /sys/kernel/config/xe/0000:03:00.0

The device created will have the following attributes to be
configured

/sys/kernel/config/xe/
.. 0000:03:00.0/
... survivability_mode

v2: fix kernel-doc
fix return value (Lucas)

v3: fix kernel-doc (Lucas)

Signed-off-by: Riana Tauro <riana.tauro@intel.com>
Reviewed-by: Lucas De Marchi <lucas.demarchi@intel.com>
Link: https://lore.kernel.org/r/20250407051414.1651616-2-riana.tauro@intel.com
Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>

authored by

Riana Tauro and committed by
Lucas De Marchi
16280ded 1e1981b1

+221
+1
Documentation/gpu/xe/index.rst
··· 25 25 xe_debugging 26 26 xe_devcoredump 27 27 xe-drm-usage-stats.rst 28 + xe_configfs
+10
Documentation/gpu/xe/xe_configfs.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0+ 2 + 3 + .. _xe_configfs: 4 + 5 + ============ 6 + Xe Configfs 7 + ============ 8 + 9 + .. kernel-doc:: drivers/gpu/drm/xe/xe_configfs.c 10 + :doc: Xe Configfs
+1
drivers/gpu/drm/xe/Makefile
··· 131 131 xe-$(CONFIG_HWMON) += xe_hwmon.o 132 132 133 133 xe-$(CONFIG_PERF_EVENTS) += xe_pmu.o 134 + xe-$(CONFIG_CONFIGFS_FS) += xe_configfs.o 134 135 135 136 # graphics virtualization (SR-IOV) support 136 137 xe-y += \
+188
drivers/gpu/drm/xe/xe_configfs.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + 6 + #include <linux/configfs.h> 7 + #include <linux/init.h> 8 + #include <linux/module.h> 9 + #include <linux/pci.h> 10 + 11 + #include "xe_configfs.h" 12 + #include "xe_module.h" 13 + 14 + /** 15 + * DOC: Xe Configfs 16 + * 17 + * Overview 18 + * ========= 19 + * 20 + * Configfs is a filesystem-based manager of kernel objects. XE KMD registers a 21 + * configfs subsystem called ``'xe'`` that creates a directory in the mounted configfs directory 22 + * The user can create devices under this directory and configure them as necessary 23 + * See Documentation/filesystems/configfs.rst for more information about how configfs works. 24 + * 25 + * Create devices 26 + * =============== 27 + * 28 + * In order to create a device, the user has to create a directory inside ``'xe'``:: 29 + * 30 + * mkdir /sys/kernel/config/xe/0000:03:00.0/ 31 + * 32 + * Every device created is populated by the driver with entries that can be 33 + * used to configure it:: 34 + * 35 + * /sys/kernel/config/xe/ 36 + * .. 0000:03:00.0/ 37 + * ... survivability_mode 38 + * 39 + * Configure Attributes 40 + * ==================== 41 + * 42 + * Survivability mode: 43 + * ------------------- 44 + * 45 + * Enable survivability mode on supported cards. This setting only takes 46 + * effect when probing the device. Example to enable it:: 47 + * 48 + * # echo 1 > /sys/kernel/config/xe/0000:03:00.0/survivability_mode 49 + * # echo 0000:03:00.0 > /sys/bus/pci/drivers/xe/bind (Enters survivability mode if supported) 50 + * 51 + * Remove devices 52 + * ============== 53 + * 54 + * The created device directories can be removed using ``rmdir``:: 55 + * 56 + * rmdir /sys/kernel/config/xe/0000:03:00.0/ 57 + */ 58 + 59 + struct xe_config_device { 60 + struct config_group group; 61 + 62 + bool survivability_mode; 63 + 64 + /* protects attributes */ 65 + struct mutex lock; 66 + }; 67 + 68 + static struct xe_config_device *to_xe_config_device(struct config_item *item) 69 + { 70 + return container_of(to_config_group(item), struct xe_config_device, group); 71 + } 72 + 73 + static ssize_t survivability_mode_show(struct config_item *item, char *page) 74 + { 75 + struct xe_config_device *dev = to_xe_config_device(item); 76 + 77 + return sprintf(page, "%d\n", dev->survivability_mode); 78 + } 79 + 80 + static ssize_t survivability_mode_store(struct config_item *item, const char *page, size_t len) 81 + { 82 + struct xe_config_device *dev = to_xe_config_device(item); 83 + bool survivability_mode; 84 + int ret; 85 + 86 + ret = kstrtobool(page, &survivability_mode); 87 + if (ret) 88 + return ret; 89 + 90 + mutex_lock(&dev->lock); 91 + dev->survivability_mode = survivability_mode; 92 + mutex_unlock(&dev->lock); 93 + 94 + return len; 95 + } 96 + 97 + CONFIGFS_ATTR(, survivability_mode); 98 + 99 + static struct configfs_attribute *xe_config_device_attrs[] = { 100 + &attr_survivability_mode, 101 + NULL, 102 + }; 103 + 104 + static void xe_config_device_release(struct config_item *item) 105 + { 106 + struct xe_config_device *dev = to_xe_config_device(item); 107 + 108 + mutex_destroy(&dev->lock); 109 + kfree(dev); 110 + } 111 + 112 + static struct configfs_item_operations xe_config_device_ops = { 113 + .release = xe_config_device_release, 114 + }; 115 + 116 + static const struct config_item_type xe_config_device_type = { 117 + .ct_item_ops = &xe_config_device_ops, 118 + .ct_attrs = xe_config_device_attrs, 119 + .ct_owner = THIS_MODULE, 120 + }; 121 + 122 + static struct config_group *xe_config_make_device_group(struct config_group *group, 123 + const char *name) 124 + { 125 + unsigned int domain, bus, slot, function; 126 + struct xe_config_device *dev; 127 + struct pci_dev *pdev; 128 + int ret; 129 + 130 + ret = sscanf(name, "%04x:%02x:%02x.%x", &domain, &bus, &slot, &function); 131 + if (ret != 4) 132 + return ERR_PTR(-EINVAL); 133 + 134 + pdev = pci_get_domain_bus_and_slot(domain, bus, PCI_DEVFN(slot, function)); 135 + if (!pdev) 136 + return ERR_PTR(-EINVAL); 137 + 138 + dev = kzalloc(sizeof(*dev), GFP_KERNEL); 139 + if (!dev) 140 + return ERR_PTR(-ENOMEM); 141 + 142 + config_group_init_type_name(&dev->group, name, &xe_config_device_type); 143 + 144 + mutex_init(&dev->lock); 145 + 146 + return &dev->group; 147 + } 148 + 149 + static struct configfs_group_operations xe_config_device_group_ops = { 150 + .make_group = xe_config_make_device_group, 151 + }; 152 + 153 + static const struct config_item_type xe_configfs_type = { 154 + .ct_group_ops = &xe_config_device_group_ops, 155 + .ct_owner = THIS_MODULE, 156 + }; 157 + 158 + static struct configfs_subsystem xe_configfs = { 159 + .su_group = { 160 + .cg_item = { 161 + .ci_namebuf = "xe", 162 + .ci_type = &xe_configfs_type, 163 + }, 164 + }, 165 + }; 166 + 167 + int __init xe_configfs_init(void) 168 + { 169 + struct config_group *root = &xe_configfs.su_group; 170 + int ret; 171 + 172 + config_group_init(root); 173 + mutex_init(&xe_configfs.su_mutex); 174 + ret = configfs_register_subsystem(&xe_configfs); 175 + if (ret) { 176 + pr_err("Error %d while registering %s subsystem\n", 177 + ret, root->cg_item.ci_namebuf); 178 + return ret; 179 + } 180 + 181 + return 0; 182 + } 183 + 184 + void __exit xe_configfs_exit(void) 185 + { 186 + configfs_unregister_subsystem(&xe_configfs); 187 + } 188 +
+16
drivers/gpu/drm/xe/xe_configfs.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Copyright © 2025 Intel Corporation 4 + */ 5 + #ifndef _XE_CONFIGFS_H_ 6 + #define _XE_CONFIGFS_H_ 7 + 8 + #if IS_ENABLED(CONFIG_CONFIGFS_FS) 9 + int xe_configfs_init(void); 10 + void xe_configfs_exit(void); 11 + #else 12 + static inline int xe_configfs_init(void) { return 0; }; 13 + static inline void xe_configfs_exit(void) {}; 14 + #endif 15 + 16 + #endif
+5
drivers/gpu/drm/xe/xe_module.c
··· 11 11 #include <drm/drm_module.h> 12 12 13 13 #include "xe_drv.h" 14 + #include "xe_configfs.h" 14 15 #include "xe_hw_fence.h" 15 16 #include "xe_pci.h" 16 17 #include "xe_pm.h" ··· 88 87 static const struct init_funcs init_funcs[] = { 89 88 { 90 89 .init = xe_check_nomodeset, 90 + }, 91 + { 92 + .init = xe_configfs_init, 93 + .exit = xe_configfs_exit, 91 94 }, 92 95 { 93 96 .init = xe_hw_fence_module_init,