diff --git a/drivers/base/auxiliary.c b/drivers/base/auxiliary.c
index afa4df4c5a3f..56a487fce053 100644
--- a/drivers/base/auxiliary.c
+++ b/drivers/base/auxiliary.c
@@ -201,6 +201,18 @@ static const struct dev_pm_ops auxiliary_dev_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(pm_generic_suspend, pm_generic_resume)
 };
 
+static void auxiliary_bus_sysfs_probe(struct auxiliary_device *auxdev)
+{
+	mutex_init(&auxdev->sysfs.lock);
+	xa_init(&auxdev->sysfs.irqs);
+}
+
+static void auxiliary_bus_sysfs_remove(struct auxiliary_device *auxdev)
+{
+	xa_destroy(&auxdev->sysfs.irqs);
+	mutex_destroy(&auxdev->sysfs.lock);
+}
+
 static int auxiliary_bus_probe(struct device *dev)
 {
 	const struct auxiliary_driver *auxdrv = to_auxiliary_drv(dev->driver);
@@ -213,10 +225,12 @@ static int auxiliary_bus_probe(struct device *dev)
 		return ret;
 	}
 
+	auxiliary_bus_sysfs_probe(auxdev);
 	ret = auxdrv->probe(auxdev, auxiliary_match_id(auxdrv->id_table, auxdev));
-	if (ret)
+	if (ret) {
+		auxiliary_bus_sysfs_remove(auxdev);
 		dev_pm_domain_detach(dev, true);
-
+	}
 	return ret;
 }
 
@@ -227,6 +241,7 @@ static void auxiliary_bus_remove(struct device *dev)
 
 	if (auxdrv->remove)
 		auxdrv->remove(auxdev);
+	auxiliary_bus_sysfs_remove(auxdev);
 	dev_pm_domain_detach(dev, true);
 }
 
@@ -287,7 +302,6 @@ int auxiliary_device_init(struct auxiliary_device *auxdev)
 
 	dev->bus = &auxiliary_bus_type;
 	device_initialize(&auxdev->dev);
-	mutex_init(&auxdev->sysfs.lock);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(auxiliary_device_init);
diff --git a/drivers/base/auxiliary_sysfs.c b/drivers/base/auxiliary_sysfs.c
index 754f21730afd..fa0eb4009f4d 100644
--- a/drivers/base/auxiliary_sysfs.c
+++ b/drivers/base/auxiliary_sysfs.c
@@ -24,19 +24,8 @@ static const struct attribute_group auxiliary_irqs_group = {
 
 static int auxiliary_irq_dir_prepare(struct auxiliary_device *auxdev)
 {
-	int ret = 0;
-
 	guard(mutex)(&auxdev->sysfs.lock);
-	if (auxdev->sysfs.irq_dir_exists)
-		return 0;
-
-	ret = devm_device_add_group(&auxdev->dev, &auxiliary_irqs_group);
-	if (ret)
-		return ret;
-
-	auxdev->sysfs.irq_dir_exists = true;
-	xa_init(&auxdev->sysfs.irqs);
-	return 0;
+	return devm_device_update_group(&auxdev->dev, &auxiliary_irqs_group);
 }
 
 /**
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 2fde698430df..5cc89528ffd2 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -2835,17 +2835,8 @@ static void devm_attr_group_remove(struct device *dev, void *res)
 	sysfs_remove_group(&dev->kobj, group);
 }
 
-/**
- * devm_device_add_group - given a device, create a managed attribute group
- * @dev:	The device to create the group for
- * @grp:	The attribute group to create
- *
- * This function creates a group for the first time.  It will explicitly
- * warn and error if any of the attribute files being created already exist.
- *
- * Returns 0 on success or error code on failure.
- */
-int devm_device_add_group(struct device *dev, const struct attribute_group *grp)
+static int __devm_device_add_group(struct device *dev, const struct attribute_group *grp,
+				   bool sysfs_update)
 {
 	union device_attr_group_devres *devres;
 	int error;
@@ -2855,7 +2846,8 @@ int devm_device_add_group(struct device *dev, const struct attribute_group *grp)
 	if (!devres)
 		return -ENOMEM;
 
-	error = sysfs_create_group(&dev->kobj, grp);
+	error = sysfs_update ? sysfs_update_group(&dev->kobj, grp) :
+			       sysfs_create_group(&dev->kobj, grp);
 	if (error) {
 		devres_free(devres);
 		return error;
@@ -2865,8 +2857,57 @@ int devm_device_add_group(struct device *dev, const struct attribute_group *grp)
 	devres_add(dev, devres);
 	return 0;
 }
+
+/**
+ * devm_device_add_group - given a device, create a managed attribute group
+ * @dev:	The device to create the group for
+ * @grp:	The attribute group to create
+ *
+ * This function creates a group for the first time.  It will explicitly
+ * warn and error if any of the attribute files being created already exist.
+ *
+ * Returns 0 on success or error code on failure.
+ */
+int devm_device_add_group(struct device *dev, const struct attribute_group *grp)
+{
+	return __devm_device_add_group(dev, grp, false);
+}
 EXPORT_SYMBOL_GPL(devm_device_add_group);
 
+static int devm_device_group_match(struct device *dev, void *res, void *grp)
+{
+	union device_attr_group_devres *devres = res;
+
+	return devres->group == grp;
+}
+
+/**
+ * devm_device_update_group - given a device, update managed attribute group
+ * @dev:	The device to update the group for
+ * @grp:	The attribute group to update
+ *
+ * This function updates a managed attribute group, create it if it does not
+ * exist and converts an unmanaged attributes group into a managed attributes
+ * group. Unlike devm_device_add_group it will explicitly not warn or error if
+ * any of the attribute files being created already exist. Furthermore, if the
+ * visibility of the files has changed through the is_visible() callback, it
+ * will update the permissions and add or remove the relevant files. Changing a
+ * group's name (subdirectory name under kobj's directory in sysfs) is not
+ * allowed.
+ *
+ * Returns 0 on success or error code on failure.
+ */
+int devm_device_update_group(struct device *dev, const struct attribute_group *grp)
+{
+	union device_attr_group_devres *devres;
+
+	devres = devres_find(dev, devm_attr_group_remove, devm_device_group_match, (void *)grp);
+
+	return devres ? sysfs_update_group(&dev->kobj, grp) :
+			__devm_device_add_group(dev, grp, true);
+}
+EXPORT_SYMBOL_GPL(devm_device_update_group);
+
 static int device_add_attrs(struct device *dev)
 {
 	const struct class *class = dev->class;
diff --git a/include/linux/auxiliary_bus.h b/include/linux/auxiliary_bus.h
index 65dd7f154374..d8684cbff54e 100644
--- a/include/linux/auxiliary_bus.h
+++ b/include/linux/auxiliary_bus.h
@@ -146,7 +146,6 @@ struct auxiliary_device {
 	struct {
 		struct xarray irqs;
 		struct mutex lock; /* Synchronize irq sysfs creation */
-		bool irq_dir_exists;
 	} sysfs;
 };
 
@@ -238,7 +237,6 @@ auxiliary_device_sysfs_irq_remove(struct auxiliary_device *auxdev, int irq) {}
 
 static inline void auxiliary_device_uninit(struct auxiliary_device *auxdev)
 {
-	mutex_destroy(&auxdev->sysfs.lock);
 	put_device(&auxdev->dev);
 }
 
diff --git a/include/linux/device.h b/include/linux/device.h
index 80a5b3268986..faec7a3fab68 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -1273,6 +1273,8 @@ static inline void device_remove_group(struct device *dev,
 
 int __must_check devm_device_add_group(struct device *dev,
 				       const struct attribute_group *grp);
+int __must_check devm_device_update_group(struct device *dev,
+					  const struct attribute_group *grp);
 
 /*
  * get_device - atomically increment the reference count for the device.
