From: Amir Tzin <redacted>
In case an auxiliary device with IRQs directory is unbound, the
directory is released, but auxdev->sysfs.irq_dir_exists remains true.
This leads to a failure recreating the directory on bind.
[] mlx5_core.sf mlx5_core.sf.2: mlx5_irq_affinity_request:167:(pid 1939):
Failed to create sysfs entry for irq 56, ret = -2
[] mlx5_core.sf mlx5_core.sf.2: mlx5_eq_table_create:1195:(pid 1939):
Failed to create async EQs
[] mlx5_core.sf mlx5_core.sf.2: mlx5_load:1362:(pid 1939):
Failed to create EQs
The irqs directory state is described by three pieces: the sysfs group,
the irq_dir_exists flag and the irqs xarray. Currently, only the sysfs
group removal is managed by the devres API, and on unbind the group is
removed while the flag and xarray are left intact. Thus, a subsequent
bind sees irq_dir_exists still set and skips recreating the directory.
Manage all three under a single release function passed to
devm_add_action_or_reset(), so the whole directory state is created and
destroyed as a unit.
Fixes: a808878308a8 ("driver core: auxiliary bus: show auxiliary device IRQs")
Suggested-by: Danilo Krummrich <dakr@kernel.org>
Signed-off-by: Amir Tzin <redacted>
Reviewed-by: Mark Bloch <mbloch@nvidia.com>
Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
---
drivers/base/auxiliary_sysfs.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
V3:
- New approach.
- Retitle, and add Danilo's Suggested-by.
- Drop Jacob's Reviewed-by, as the approach changed.
V2:
https://lore.kernel.org/all/20260219210435.1769394-1-tariqt@nvidia.com/ (local)
V1:
https://lore.kernel.org/all/1761200367-922346-1-git-send-email-tariqt@nvidia.com/ (local)
diff --git a/drivers/base/auxiliary_sysfs.c b/drivers/base/auxiliary_sysfs.c
index dea7f46f7dd0..656ba057dc98 100644
--- a/drivers/base/auxiliary_sysfs.c
+++ b/drivers/base/auxiliary_sysfs.c
@@ -22,21 +22,32 @@ static const struct attribute_group auxiliary_irqs_group = {
.attrs = auxiliary_irq_attrs,
};
+static void auxiliary_irq_dir_release(void *data)
+{
+ struct auxiliary_device *auxdev = data;
+
+ xa_destroy(&auxdev->sysfs.irqs);
+ auxdev->sysfs.irq_dir_exists = false;
+ sysfs_remove_group(&auxdev->dev.kobj, &auxiliary_irqs_group);
+}
+
static int auxiliary_irq_dir_prepare(struct auxiliary_device *auxdev)
{
- int ret = 0;
+ int ret;
guard(mutex)(&auxdev->sysfs.lock);
if (auxdev->sysfs.irq_dir_exists)
return 0;
- ret = devm_device_add_group(&auxdev->dev, &auxiliary_irqs_group);
+ ret = sysfs_create_group(&auxdev->dev.kobj, &auxiliary_irqs_group);
if (ret)
return ret;
auxdev->sysfs.irq_dir_exists = true;
xa_init(&auxdev->sysfs.irqs);
- return 0;
+
+ return devm_add_action_or_reset(&auxdev->dev,
+ auxiliary_irq_dir_release, auxdev);
}
/**
base-commit: b71c101bbb9814d163c00234d43c41f0a17907d4
--
2.44.0