summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Wajdeczko <michal.wajdeczko@intel.com>2026-02-04 02:53:32 +0300
committerMichal Wajdeczko <michal.wajdeczko@intel.com>2026-02-05 22:57:13 +0300
commit98b16727f07e26a5d4de84d88805ce7ffcfdd324 (patch)
treee65c8297be6fcc38716bb25a7d9e374ebcfef3e1
parentf27e64422054ff78566316509120f7ee2ecc7660 (diff)
downloadlinux-98b16727f07e26a5d4de84d88805ce7ffcfdd324.tar.xz
drm/xe/pf: Fix sysfs initialization
In case of devm_add_action_or_reset() failure the provided cleanup action will be run immediately on the not yet initialized kobject. This may lead to errors like: [ ] kobject: '(null)' (ff110001393608e0): is not initialized, yet kobject_put() is being called. [ ] WARNING: lib/kobject.c:734 at kobject_put+0xd9/0x250, CPU#0: kworker/0:0/9 [ ] RIP: 0010:kobject_put+0xdf/0x250 [ ] Call Trace: [ ] xe_sriov_pf_sysfs_init+0x21/0x100 [xe] [ ] xe_sriov_pf_init_late+0x87/0x2b0 [xe] [ ] xe_sriov_init_late+0x5f/0x2c0 [xe] [ ] xe_device_probe+0x5f2/0xc20 [xe] [ ] xe_pci_probe+0x396/0x610 [xe] [ ] local_pci_probe+0x47/0xb0 [ ] refcount_t: underflow; use-after-free. [ ] WARNING: lib/refcount.c:28 at refcount_warn_saturate+0x68/0xb0, CPU#0: kworker/0:0/9 [ ] RIP: 0010:refcount_warn_saturate+0x68/0xb0 [ ] Call Trace: [ ] kobject_put+0x174/0x250 [ ] xe_sriov_pf_sysfs_init+0x21/0x100 [xe] [ ] xe_sriov_pf_init_late+0x87/0x2b0 [xe] [ ] xe_sriov_init_late+0x5f/0x2c0 [xe] [ ] xe_device_probe+0x5f2/0xc20 [xe] [ ] xe_pci_probe+0x396/0x610 [xe] [ ] local_pci_probe+0x47/0xb0 Fix that by calling kobject_init() and kobject_add() separately and register cleanup action after the kobject is initialized. Also make this cleanup registration a part of the create helper to fix another mistake, as in the loop we were wrongly passing parent kobject while registering cleanup action, and this resulted in some undetected leaks. Fixes: 5c170a4d9c53 ("drm/xe/pf: Prepare sysfs for SR-IOV admin attributes") Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> Reviewed-by: Shuicheng Lin <shuicheng.lin@intel.com> Link: https://patch.msgid.link/20260203235332.1350-1-michal.wajdeczko@intel.com
-rw-r--r--drivers/gpu/drm/xe/xe_sriov_pf_sysfs.c54
1 files changed, 26 insertions, 28 deletions
diff --git a/drivers/gpu/drm/xe/xe_sriov_pf_sysfs.c b/drivers/gpu/drm/xe/xe_sriov_pf_sysfs.c
index 3d140506ba36..82a1055985ba 100644
--- a/drivers/gpu/drm/xe/xe_sriov_pf_sysfs.c
+++ b/drivers/gpu/drm/xe/xe_sriov_pf_sysfs.c
@@ -349,18 +349,33 @@ static const struct attribute_group *xe_sriov_vf_attr_groups[] = {
/* no user serviceable parts below */
-static struct kobject *create_xe_sriov_kobj(struct xe_device *xe, unsigned int vfid)
+static void action_put_kobject(void *arg)
+{
+ struct kobject *kobj = arg;
+
+ kobject_put(kobj);
+}
+
+static struct kobject *create_xe_sriov_kobj(struct xe_device *xe, unsigned int vfid,
+ const struct kobj_type *ktype)
{
struct xe_sriov_kobj *vkobj;
+ int err;
xe_sriov_pf_assert_vfid(xe, vfid);
vkobj = kzalloc(sizeof(*vkobj), GFP_KERNEL);
if (!vkobj)
- return NULL;
+ return ERR_PTR(-ENOMEM);
vkobj->xe = xe;
vkobj->vfid = vfid;
+ kobject_init(&vkobj->base, ktype);
+
+ err = devm_add_action_or_reset(xe->drm.dev, action_put_kobject, &vkobj->base);
+ if (err)
+ return ERR_PTR(err);
+
return &vkobj->base;
}
@@ -463,28 +478,17 @@ static void pf_sysfs_note(struct xe_device *xe, int err, const char *what)
xe_sriov_dbg(xe, "Failed to setup sysfs %s (%pe)\n", what, ERR_PTR(err));
}
-static void action_put_kobject(void *arg)
-{
- struct kobject *kobj = arg;
-
- kobject_put(kobj);
-}
-
static int pf_setup_root(struct xe_device *xe)
{
struct kobject *parent = &xe->drm.dev->kobj;
struct kobject *root;
int err;
- root = create_xe_sriov_kobj(xe, PFID);
- if (!root)
- return pf_sysfs_error(xe, -ENOMEM, "root obj");
-
- err = devm_add_action_or_reset(xe->drm.dev, action_put_kobject, root);
- if (err)
- return pf_sysfs_error(xe, err, "root action");
+ root = create_xe_sriov_kobj(xe, PFID, &xe_sriov_dev_ktype);
+ if (IS_ERR(root))
+ return pf_sysfs_error(xe, PTR_ERR(root), "root obj");
- err = kobject_init_and_add(root, &xe_sriov_dev_ktype, parent, "sriov_admin");
+ err = kobject_add(root, parent, "sriov_admin");
if (err)
return pf_sysfs_error(xe, err, "root init");
@@ -505,20 +509,14 @@ static int pf_setup_tree(struct xe_device *xe)
root = xe->sriov.pf.sysfs.root;
for (n = 0; n <= totalvfs; n++) {
- kobj = create_xe_sriov_kobj(xe, VFID(n));
- if (!kobj)
- return pf_sysfs_error(xe, -ENOMEM, "tree obj");
-
- err = devm_add_action_or_reset(xe->drm.dev, action_put_kobject, root);
- if (err)
- return pf_sysfs_error(xe, err, "tree action");
+ kobj = create_xe_sriov_kobj(xe, VFID(n), &xe_sriov_vf_ktype);
+ if (IS_ERR(kobj))
+ return pf_sysfs_error(xe, PTR_ERR(kobj), "tree obj");
if (n)
- err = kobject_init_and_add(kobj, &xe_sriov_vf_ktype,
- root, "vf%u", n);
+ err = kobject_add(kobj, root, "vf%u", n);
else
- err = kobject_init_and_add(kobj, &xe_sriov_vf_ktype,
- root, "pf");
+ err = kobject_add(kobj, root, "pf");
if (err)
return pf_sysfs_error(xe, err, "tree init");