blob: 539bd3a2671206cf6f5347b22cb7fe8c268f3b0f [file]
From 9e56a23cd646ae886dae8e2157a6b745b738af74 Mon Sep 17 00:00:00 2001
From: Sasha Levin <sashal@kernel.org>
Date: Wed, 4 Feb 2026 00:53:32 +0100
Subject: drm/xe/pf: Fix sysfs initialization
From: Michal Wajdeczko <michal.wajdeczko@intel.com>
[ Upstream commit bf7172cd25ed182f30af2cbb9f80c730dc717d8e ]
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
(cherry picked from commit 98b16727f07e26a5d4de84d88805ce7ffcfdd324)
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/xe/xe_sriov_pf_sysfs.c | 54 +++++++++++++-------------
1 file 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 c0b767ac735cf..d1c1f6c295664 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;
}
@@ -471,28 +486,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");
@@ -513,20 +517,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");
--
2.51.0