regulator: core: Decouple regulators on regulator_unregister()
authorDmitry Osipenko <digetx@gmail.com>
Fri, 5 Oct 2018 15:36:36 +0000 (18:36 +0300)
committerMark Brown <broonie@kernel.org>
Thu, 8 Nov 2018 16:20:50 +0000 (16:20 +0000)
Regulators shall be uncoupled if one of the couples disappear.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/regulator/core.c

index ba03bdf3716f66e6dcc5695065db22e8ac4fb735..783ec9c74104659f558d871d78fb629aee60b497 100644 (file)
@@ -4518,6 +4518,43 @@ static void regulator_resolve_coupling(struct regulator_dev *rdev)
        }
 }
 
+static void regulator_remove_coupling(struct regulator_dev *rdev)
+{
+       struct coupling_desc *__c_desc, *c_desc = &rdev->coupling_desc;
+       struct regulator_dev *__c_rdev, *c_rdev;
+       unsigned int __n_coupled, n_coupled;
+       int i, k;
+
+       n_coupled = c_desc->n_coupled;
+
+       for (i = 1; i < n_coupled; i++) {
+               c_rdev = c_desc->coupled_rdevs[i];
+
+               if (!c_rdev)
+                       continue;
+
+               regulator_lock(c_rdev);
+
+               __c_desc = &c_rdev->coupling_desc;
+               __n_coupled = __c_desc->n_coupled;
+
+               for (k = 1; k < __n_coupled; k++) {
+                       __c_rdev = __c_desc->coupled_rdevs[k];
+
+                       if (__c_rdev == rdev) {
+                               __c_desc->coupled_rdevs[k] = NULL;
+                               __c_desc->n_resolved--;
+                               break;
+                       }
+               }
+
+               regulator_unlock(c_rdev);
+
+               c_desc->coupled_rdevs[i] = NULL;
+               c_desc->n_resolved--;
+       }
+}
+
 static int regulator_init_coupling(struct regulator_dev *rdev)
 {
        int n_phandles;
@@ -4776,6 +4813,7 @@ void regulator_unregister(struct regulator_dev *rdev)
        debugfs_remove_recursive(rdev->debugfs);
        flush_work(&rdev->disable_work.work);
        WARN_ON(rdev->open_count);
+       regulator_remove_coupling(rdev);
        unset_regulator_supplies(rdev);
        list_del(&rdev->list);
        regulator_ena_gpio_free(rdev);