| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| From: Saravana Kannan <saravanak@google.com> |
| Date: Thu, 14 Nov 2019 16:04:38 -0800 |
| Subject: UPSTREAM: regulator: core: Don't try to remove device links if add |
| failed |
| |
| device_link_add() might not always succeed depending on the type of |
| device link and the rest of the dependencies in the system. If |
| device_link_add() didn't succeed, then we shouldn't try to remove the |
| link later on as it might remove a link someone else created. |
| |
| Signed-off-by: Saravana Kannan <saravanak@google.com> |
| Link: https://lore.kernel.org/r/20191115000438.45970-1-saravanak@google.com |
| Signed-off-by: Mark Brown <broonie@kernel.org> |
| (cherry-picked from b59b654478093fa429ad4c7897ae29f201146a00) |
| Change-Id: I6cffa3ca884b74122307931e8f6615f31c33ef55 |
| --- |
| drivers/regulator/core.c | 8 ++++++-- |
| drivers/regulator/internal.h | 1 + |
| 2 files changed, 7 insertions(+), 2 deletions(-) |
| |
| diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c |
| index 1dba0bdf3762..fc91952c4127 100644 |
| --- a/drivers/regulator/core.c |
| +++ b/drivers/regulator/core.c |
| @@ -1846,6 +1846,7 @@ struct regulator *_regulator_get(struct device *dev, const char *id, |
| struct regulator_dev *rdev; |
| struct regulator *regulator; |
| const char *devname = dev ? dev_name(dev) : "deviceless"; |
| + struct device_link *link; |
| int ret; |
| |
| if (get_type >= MAX_GET_TYPE) { |
| @@ -1953,7 +1954,9 @@ struct regulator *_regulator_get(struct device *dev, const char *id, |
| rdev->use_count = 0; |
| } |
| |
| - device_link_add(dev, &rdev->dev, DL_FLAG_STATELESS); |
| + link = device_link_add(dev, &rdev->dev, DL_FLAG_STATELESS); |
| + if (!IS_ERR_OR_NULL(link)) |
| + regulator->device_link = true; |
| |
| return regulator; |
| } |
| @@ -2048,7 +2051,8 @@ static void _regulator_put(struct regulator *regulator) |
| debugfs_remove_recursive(regulator->debugfs); |
| |
| if (regulator->dev) { |
| - device_link_remove(regulator->dev, &rdev->dev); |
| + if (regulator->device_link) |
| + device_link_remove(regulator->dev, &rdev->dev); |
| |
| /* remove any sysfs entries */ |
| sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); |
| diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h |
| index 83ae442f515b..2391b565ef11 100644 |
| --- a/drivers/regulator/internal.h |
| +++ b/drivers/regulator/internal.h |
| @@ -36,6 +36,7 @@ struct regulator { |
| struct list_head list; |
| unsigned int always_on:1; |
| unsigned int bypass:1; |
| + unsigned int device_link:1; |
| int uA_load; |
| unsigned int enable_count; |
| unsigned int deferred_disables; |