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

drm/xe/pf: Allow to stop the VF using sysfs

It is expected that VFs activity will be monitored and in some
cases admin might want to silence specific VF without killing
the VM where it was attached.

Add write-only attribute to stop GuC scheduling at VFs level.

/sys/bus/pci/drivers/xe/BDF/
├── sriov_admin/
├── vf1/
│ └── stop [WO] bool
├── vf2/
│ └── stop [WO] bool

Writing "1" or "y" (or whatever is recognized by the strtobool()
function) to this file will trigger the change of the VF state
to STOP (GuC will stop servicing the VF). To go back to a READY
state (to allow GuC to service this VF again) the VF FLR must be
triggered (which can be done by writing 1 to device/reset file).

Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Lucas De Marchi <lucas.demarchi@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Reviewed-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
Reviewed-by: Lucas De Marchi <lucas.demarchi@intel.com>
Link: https://patch.msgid.link/20251030222348.186658-17-michal.wajdeczko@intel.com

+49
+49
drivers/gpu/drm/xe/xe_sriov_pf_sysfs.c
··· 13 13 #include "xe_pm.h" 14 14 #include "xe_sriov.h" 15 15 #include "xe_sriov_pf.h" 16 + #include "xe_sriov_pf_control.h" 16 17 #include "xe_sriov_pf_helpers.h" 17 18 #include "xe_sriov_pf_provision.h" 18 19 #include "xe_sriov_pf_sysfs.h" ··· 55 54 * ├── vf1/ 56 55 * │ ├── ... 57 56 * │ ├── device -> ../../../BDF.1 57 + * │ ├── stop 58 58 * │ └── profile 59 59 * │ ├── exec_quantum_ms 60 60 * │ ├── preempt_timeout_us ··· 295 293 .is_visible = profile_vf_attr_is_visible, 296 294 }; 297 295 296 + #define DEFINE_SIMPLE_CONTROL_SRIOV_VF_ATTR(NAME) \ 297 + \ 298 + static ssize_t xe_sriov_vf_attr_##NAME##_store(struct xe_device *xe, unsigned int vfid, \ 299 + const char *buf, size_t count) \ 300 + { \ 301 + bool yes; \ 302 + int err; \ 303 + \ 304 + if (!vfid) \ 305 + return -EPERM; \ 306 + \ 307 + err = kstrtobool(buf, &yes); \ 308 + if (err) \ 309 + return err; \ 310 + if (!yes) \ 311 + return count; \ 312 + \ 313 + err = xe_sriov_pf_control_##NAME##_vf(xe, vfid); \ 314 + return err ?: count; \ 315 + } \ 316 + \ 317 + static XE_SRIOV_VF_ATTR_WO(NAME) 318 + 319 + DEFINE_SIMPLE_CONTROL_SRIOV_VF_ATTR(stop); 320 + 321 + static struct attribute *control_vf_attrs[] = { 322 + &xe_sriov_vf_attr_stop.attr, 323 + NULL 324 + }; 325 + 326 + static umode_t control_vf_attr_is_visible(struct kobject *kobj, 327 + struct attribute *attr, int index) 328 + { 329 + struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); 330 + 331 + if (vkobj->vfid == PFID) 332 + return 0; 333 + 334 + return attr->mode; 335 + } 336 + 337 + static const struct attribute_group control_vf_attr_group = { 338 + .attrs = control_vf_attrs, 339 + .is_visible = control_vf_attr_is_visible, 340 + }; 341 + 298 342 static const struct attribute_group *xe_sriov_vf_attr_groups[] = { 299 343 &profile_vf_attr_group, 344 + &control_vf_attr_group, 300 345 NULL 301 346 }; 302 347