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

Configure Feed

Select the types of activity you want to include in your feed.

at v6.16 250 lines 6.0 kB view raw
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 59struct xe_config_device { 60 struct config_group group; 61 62 bool survivability_mode; 63 64 /* protects attributes */ 65 struct mutex lock; 66}; 67 68static 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 73static 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 80static 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 97CONFIGFS_ATTR(, survivability_mode); 98 99static struct configfs_attribute *xe_config_device_attrs[] = { 100 &attr_survivability_mode, 101 NULL, 102}; 103 104static 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 112static struct configfs_item_operations xe_config_device_ops = { 113 .release = xe_config_device_release, 114}; 115 116static 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 122static 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 149static struct configfs_group_operations xe_config_device_group_ops = { 150 .make_group = xe_config_make_device_group, 151}; 152 153static const struct config_item_type xe_configfs_type = { 154 .ct_group_ops = &xe_config_device_group_ops, 155 .ct_owner = THIS_MODULE, 156}; 157 158static 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 167static struct xe_config_device *configfs_find_group(struct pci_dev *pdev) 168{ 169 struct config_item *item; 170 char name[64]; 171 172 snprintf(name, sizeof(name), "%04x:%02x:%02x.%x", pci_domain_nr(pdev->bus), 173 pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); 174 175 mutex_lock(&xe_configfs.su_mutex); 176 item = config_group_find_item(&xe_configfs.su_group, name); 177 mutex_unlock(&xe_configfs.su_mutex); 178 179 if (!item) 180 return NULL; 181 182 return to_xe_config_device(item); 183} 184 185/** 186 * xe_configfs_get_survivability_mode - get configfs survivability mode attribute 187 * @pdev: pci device 188 * 189 * find the configfs group that belongs to the pci device and return 190 * the survivability mode attribute 191 * 192 * Return: survivability mode if config group is found, false otherwise 193 */ 194bool xe_configfs_get_survivability_mode(struct pci_dev *pdev) 195{ 196 struct xe_config_device *dev = configfs_find_group(pdev); 197 bool mode; 198 199 if (!dev) 200 return false; 201 202 mode = dev->survivability_mode; 203 config_item_put(&dev->group.cg_item); 204 205 return mode; 206} 207 208/** 209 * xe_configfs_clear_survivability_mode - clear configfs survivability mode attribute 210 * @pdev: pci device 211 * 212 * find the configfs group that belongs to the pci device and clear survivability 213 * mode attribute 214 */ 215void xe_configfs_clear_survivability_mode(struct pci_dev *pdev) 216{ 217 struct xe_config_device *dev = configfs_find_group(pdev); 218 219 if (!dev) 220 return; 221 222 mutex_lock(&dev->lock); 223 dev->survivability_mode = 0; 224 mutex_unlock(&dev->lock); 225 226 config_item_put(&dev->group.cg_item); 227} 228 229int __init xe_configfs_init(void) 230{ 231 struct config_group *root = &xe_configfs.su_group; 232 int ret; 233 234 config_group_init(root); 235 mutex_init(&xe_configfs.su_mutex); 236 ret = configfs_register_subsystem(&xe_configfs); 237 if (ret) { 238 pr_err("Error %d while registering %s subsystem\n", 239 ret, root->cg_item.ci_namebuf); 240 return ret; 241 } 242 243 return 0; 244} 245 246void __exit xe_configfs_exit(void) 247{ 248 configfs_unregister_subsystem(&xe_configfs); 249} 250