Commit 8b6ce251 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'regulator-fix-v5.9-rc4' of...

Merge tag 'regulator-fix-v5.9-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator

Pull regulator fixes from Mark Brown:
 "The biggest set of fixes here is those from Michał Mirosław fixing
  some locking issues with coupled regulators that are triggered in
  cases where a coupled regulator is used by a device involved in
  fs_reclaim like eMMC storage.

  These are relatively serious for the affected systems, though the
  circumstances where they trigger are very rare"

* tag 'regulator-fix-v5.9-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator:
  regulator: pwm: Fix machine constraints application
  regulator: core: Fix slab-out-of-bounds in regulator_unlock_recursive()
  regulator: remove superfluous lock in regulator_resolve_coupling()
  regulator: cleanup regulator_ena_gpio_free()
  regulator: plug of_node leak in regulator_register()'s error path
  regulator: push allocation in set_consumer_device_supply() out of lock
  regulator: push allocations in create_regulator() outside of lock
  regulator: push allocation in regulator_ena_gpio_request() out of lock
  regulator: push allocation in regulator_init_coupling() outside of lock
  regulator: fix spelling mistake "Cant" -> "Can't"
  regulator: cros-ec-regulator: Add NULL test for devm_kmemdup call
parents 063d6a4c 59ae97a7
Loading
Loading
Loading
Loading
+96 −83
Original line number Diff line number Diff line
@@ -236,8 +236,8 @@ static bool regulator_supply_is_couple(struct regulator_dev *rdev)
static void regulator_unlock_recursive(struct regulator_dev *rdev,
				       unsigned int n_coupled)
{
	struct regulator_dev *c_rdev;
	int i;
	struct regulator_dev *c_rdev, *supply_rdev;
	int i, supply_n_coupled;

	for (i = n_coupled; i > 0; i--) {
		c_rdev = rdev->coupling_desc.coupled_rdevs[i - 1];
@@ -245,10 +245,13 @@ static void regulator_unlock_recursive(struct regulator_dev *rdev,
		if (!c_rdev)
			continue;

		if (c_rdev->supply && !regulator_supply_is_couple(c_rdev))
			regulator_unlock_recursive(
					c_rdev->supply->rdev,
					c_rdev->coupling_desc.n_coupled);
		if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) {
			supply_rdev = c_rdev->supply->rdev;
			supply_n_coupled = supply_rdev->coupling_desc.n_coupled;

			regulator_unlock_recursive(supply_rdev,
						   supply_n_coupled);
		}

		regulator_unlock(c_rdev);
	}
@@ -1461,7 +1464,7 @@ static int set_consumer_device_supply(struct regulator_dev *rdev,
				      const char *consumer_dev_name,
				      const char *supply)
{
	struct regulator_map *node;
	struct regulator_map *node, *new_node;
	int has_dev;

	if (supply == NULL)
@@ -1472,6 +1475,22 @@ static int set_consumer_device_supply(struct regulator_dev *rdev,
	else
		has_dev = 0;

	new_node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL);
	if (new_node == NULL)
		return -ENOMEM;

	new_node->regulator = rdev;
	new_node->supply = supply;

	if (has_dev) {
		new_node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL);
		if (new_node->dev_name == NULL) {
			kfree(new_node);
			return -ENOMEM;
		}
	}

	mutex_lock(&regulator_list_mutex);
	list_for_each_entry(node, &regulator_map_list, list) {
		if (node->dev_name && consumer_dev_name) {
			if (strcmp(node->dev_name, consumer_dev_name) != 0)
@@ -1489,26 +1508,19 @@ static int set_consumer_device_supply(struct regulator_dev *rdev,
			 node->regulator->desc->name,
			 supply,
			 dev_name(&rdev->dev), rdev_get_name(rdev));
		return -EBUSY;
		goto fail;
	}

	node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL);
	if (node == NULL)
		return -ENOMEM;

	node->regulator = rdev;
	node->supply = supply;

	if (has_dev) {
		node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL);
		if (node->dev_name == NULL) {
			kfree(node);
			return -ENOMEM;
		}
	}
	list_add(&new_node->list, &regulator_map_list);
	mutex_unlock(&regulator_list_mutex);

	list_add(&node->list, &regulator_map_list);
	return 0;

fail:
	mutex_unlock(&regulator_list_mutex);
	kfree(new_node->dev_name);
	kfree(new_node);
	return -EBUSY;
}

static void unset_regulator_supplies(struct regulator_dev *rdev)
@@ -1580,44 +1592,53 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
					  const char *supply_name)
{
	struct regulator *regulator;
	int err;

	if (dev) {
		char buf[REG_STR_SIZE];
	int err, size;
		int size;

		size = snprintf(buf, REG_STR_SIZE, "%s-%s",
				dev->kobj.name, supply_name);
		if (size >= REG_STR_SIZE)
			return NULL;

		supply_name = kstrdup(buf, GFP_KERNEL);
		if (supply_name == NULL)
			return NULL;
	} else {
		supply_name = kstrdup_const(supply_name, GFP_KERNEL);
		if (supply_name == NULL)
			return NULL;
	}

	regulator = kzalloc(sizeof(*regulator), GFP_KERNEL);
	if (regulator == NULL)
	if (regulator == NULL) {
		kfree(supply_name);
		return NULL;
	}

	regulator_lock(rdev);
	regulator->rdev = rdev;
	regulator->supply_name = supply_name;

	regulator_lock(rdev);
	list_add(&regulator->list, &rdev->consumer_list);
	regulator_unlock(rdev);

	if (dev) {
		regulator->dev = dev;

		/* Add a link to the device sysfs entry */
		size = snprintf(buf, REG_STR_SIZE, "%s-%s",
				dev->kobj.name, supply_name);
		if (size >= REG_STR_SIZE)
			goto overflow_err;

		regulator->supply_name = kstrdup(buf, GFP_KERNEL);
		if (regulator->supply_name == NULL)
			goto overflow_err;

		err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj,
					buf);
					       supply_name);
		if (err) {
			rdev_dbg(rdev, "could not add device link %s err %d\n",
				  dev->kobj.name, err);
			/* non-fatal */
		}
	} else {
		regulator->supply_name = kstrdup_const(supply_name, GFP_KERNEL);
		if (regulator->supply_name == NULL)
			goto overflow_err;
	}

	regulator->debugfs = debugfs_create_dir(regulator->supply_name,
	regulator->debugfs = debugfs_create_dir(supply_name,
						rdev->debugfs);
	if (!regulator->debugfs) {
		rdev_dbg(rdev, "Failed to create debugfs directory\n");
@@ -1642,13 +1663,7 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
	    _regulator_is_enabled(rdev))
		regulator->always_on = true;

	regulator_unlock(rdev);
	return regulator;
overflow_err:
	list_del(&regulator->list);
	kfree(regulator);
	regulator_unlock(rdev);
	return NULL;
}

static int _regulator_get_enable_time(struct regulator_dev *rdev)
@@ -2230,10 +2245,13 @@ EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias);
static int regulator_ena_gpio_request(struct regulator_dev *rdev,
				const struct regulator_config *config)
{
	struct regulator_enable_gpio *pin;
	struct regulator_enable_gpio *pin, *new_pin;
	struct gpio_desc *gpiod;

	gpiod = config->ena_gpiod;
	new_pin = kzalloc(sizeof(*new_pin), GFP_KERNEL);

	mutex_lock(&regulator_list_mutex);

	list_for_each_entry(pin, &regulator_ena_gpio_list, list) {
		if (pin->gpiod == gpiod) {
@@ -2242,9 +2260,13 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev,
		}
	}

	pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL);
	if (pin == NULL)
	if (new_pin == NULL) {
		mutex_unlock(&regulator_list_mutex);
		return -ENOMEM;
	}

	pin = new_pin;
	new_pin = NULL;

	pin->gpiod = gpiod;
	list_add(&pin->list, &regulator_ena_gpio_list);
@@ -2252,6 +2274,10 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev,
update_ena_gpio_to_rdev:
	pin->request_count++;
	rdev->ena_pin = pin;

	mutex_unlock(&regulator_list_mutex);
	kfree(new_pin);

	return 0;
}

@@ -2264,19 +2290,19 @@ static void regulator_ena_gpio_free(struct regulator_dev *rdev)

	/* Free the GPIO only in case of no use */
	list_for_each_entry_safe(pin, n, &regulator_ena_gpio_list, list) {
		if (pin->gpiod == rdev->ena_pin->gpiod) {
			if (pin->request_count <= 1) {
				pin->request_count = 0;
		if (pin != rdev->ena_pin)
			continue;

		if (--pin->request_count)
			break;

		gpiod_put(pin->gpiod);
		list_del(&pin->list);
		kfree(pin);
				rdev->ena_pin = NULL;
				return;
			} else {
				pin->request_count--;
			}
		}
		break;
	}

	rdev->ena_pin = NULL;
}

/**
@@ -4949,13 +4975,9 @@ static void regulator_resolve_coupling(struct regulator_dev *rdev)
			return;
		}

		regulator_lock(c_rdev);

		c_desc->coupled_rdevs[i] = c_rdev;
		c_desc->n_resolved++;

		regulator_unlock(c_rdev);

		regulator_resolve_coupling(c_rdev);
	}
}
@@ -5040,7 +5062,10 @@ static int regulator_init_coupling(struct regulator_dev *rdev)
	if (!of_check_coupling_data(rdev))
		return -EPERM;

	mutex_lock(&regulator_list_mutex);
	rdev->coupling_desc.coupler = regulator_find_coupler(rdev);
	mutex_unlock(&regulator_list_mutex);

	if (IS_ERR(rdev->coupling_desc.coupler)) {
		err = PTR_ERR(rdev->coupling_desc.coupler);
		rdev_err(rdev, "failed to get coupler: %d\n", err);
@@ -5141,6 +5166,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
		ret = -ENOMEM;
		goto rinse;
	}
	device_initialize(&rdev->dev);

	/*
	 * Duplicate the config so the driver could override it after
@@ -5148,9 +5174,8 @@ regulator_register(const struct regulator_desc *regulator_desc,
	 */
	config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL);
	if (config == NULL) {
		kfree(rdev);
		ret = -ENOMEM;
		goto rinse;
		goto clean;
	}

	init_data = regulator_of_get_init_data(dev, regulator_desc, config,
@@ -5162,10 +5187,8 @@ regulator_register(const struct regulator_desc *regulator_desc,
	 * from a gpio extender or something else.
	 */
	if (PTR_ERR(init_data) == -EPROBE_DEFER) {
		kfree(config);
		kfree(rdev);
		ret = -EPROBE_DEFER;
		goto rinse;
		goto clean;
	}

	/*
@@ -5206,9 +5229,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
	}

	if (config->ena_gpiod) {
		mutex_lock(&regulator_list_mutex);
		ret = regulator_ena_gpio_request(rdev, config);
		mutex_unlock(&regulator_list_mutex);
		if (ret != 0) {
			rdev_err(rdev, "Failed to request enable GPIO: %d\n",
				 ret);
@@ -5220,7 +5241,6 @@ regulator_register(const struct regulator_desc *regulator_desc,
	}

	/* register with sysfs */
	device_initialize(&rdev->dev);
	rdev->dev.class = &regulator_class;
	rdev->dev.parent = dev;
	dev_set_name(&rdev->dev, "regulator.%lu",
@@ -5248,27 +5268,22 @@ regulator_register(const struct regulator_desc *regulator_desc,
	if (ret < 0)
		goto wash;

	mutex_lock(&regulator_list_mutex);
	ret = regulator_init_coupling(rdev);
	mutex_unlock(&regulator_list_mutex);
	if (ret < 0)
		goto wash;

	/* add consumers devices */
	if (init_data) {
		mutex_lock(&regulator_list_mutex);
		for (i = 0; i < init_data->num_consumer_supplies; i++) {
			ret = set_consumer_device_supply(rdev,
				init_data->consumer_supplies[i].dev_name,
				init_data->consumer_supplies[i].supply);
			if (ret < 0) {
				mutex_unlock(&regulator_list_mutex);
				dev_err(dev, "Failed to set supply %s\n",
					init_data->consumer_supplies[i].supply);
				goto unset_supplies;
			}
		}
		mutex_unlock(&regulator_list_mutex);
	}

	if (!rdev->desc->ops->get_voltage &&
@@ -5303,13 +5318,11 @@ wash:
	mutex_lock(&regulator_list_mutex);
	regulator_ena_gpio_free(rdev);
	mutex_unlock(&regulator_list_mutex);
	put_device(&rdev->dev);
	rdev = NULL;
clean:
	if (dangling_of_gpiod)
		gpiod_put(config->ena_gpiod);
	kfree(rdev);
	kfree(config);
	put_device(&rdev->dev);
rinse:
	if (dangling_cfg_gpiod)
		gpiod_put(cfg->ena_gpiod);
+3 −0
Original line number Diff line number Diff line
@@ -170,6 +170,9 @@ static int cros_ec_regulator_init_info(struct device *dev,
	data->voltages_mV =
		devm_kmemdup(dev, resp.voltages_mv,
			     sizeof(u16) * data->num_voltages, GFP_KERNEL);
	if (!data->voltages_mV)
		return -ENOMEM;

	data->desc.n_voltages = data->num_voltages;

	/* Make sure the returned name is always a valid string */
+1 −1
Original line number Diff line number Diff line
@@ -182,7 +182,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)

		drvdata->enable_clock = devm_clk_get(dev, NULL);
		if (IS_ERR(drvdata->enable_clock)) {
			dev_err(dev, "Cant get enable-clock from devicetree\n");
			dev_err(dev, "Can't get enable-clock from devicetree\n");
			return -ENOENT;
		}
	} else {
+1 −1
Original line number Diff line number Diff line
@@ -279,7 +279,7 @@ static int pwm_regulator_init_table(struct platform_device *pdev,
		return ret;
	}

	drvdata->state			= -EINVAL;
	drvdata->state			= -ENOTRECOVERABLE;
	drvdata->duty_cycle_table	= duty_cycle_table;
	drvdata->desc.ops = &pwm_regulator_voltage_table_ops;
	drvdata->desc.n_voltages	= length / sizeof(*duty_cycle_table);