Commit 05947224 authored by Uwe Kleine-König's avatar Uwe Kleine-König
Browse files

pwm: Ensure that pwm_chips are allocated using pwmchip_alloc()

Memory holding a struct device must not be freed before the reference
count drops to zero. So a struct pwm_chip must not live in memory
freed by a driver on unbind. All in-tree drivers were fixed accordingly,
but as out-of-tree drivers, that were not adapted, still compile fine,
catch these in pwmchip_add().

Link: https://lore.kernel.org/r/35f5b229c98f78b2f6ce2397259a4a936be477c0.1707900770.git.u.kleine-koenig@pengutronix.de


Signed-off-by: default avatarUwe Kleine-König <u.kleine-koenig@pengutronix.de>
parent 79dedfad
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -481,6 +481,7 @@ struct pwm_chip *pwmchip_alloc(struct device *parent, unsigned int npwm, size_t

	chip->dev = parent;
	chip->npwm = npwm;
	chip->uses_pwmchip_alloc = true;

	pwmchip_set_drvdata(chip, pwmchip_priv(chip));

@@ -561,6 +562,15 @@ int __pwmchip_add(struct pwm_chip *chip, struct module *owner)
	if (!chip || !pwmchip_parent(chip) || !chip->ops || !chip->npwm)
		return -EINVAL;

	/*
	 * a struct pwm_chip must be allocated using (devm_)pwmchip_alloc,
	 * otherwise the embedded struct device might disappear too early
	 * resulting in memory corruption.
	 * Catch drivers that were not converted appropriately.
	 */
	if (!chip->uses_pwmchip_alloc)
		return -EINVAL;

	if (!pwm_ops_check(chip))
		return -EINVAL;

+2 −0
Original line number Diff line number Diff line
@@ -272,6 +272,7 @@ struct pwm_ops {
 * @npwm: number of PWMs controlled by this chip
 * @of_xlate: request a PWM device given a device tree PWM specifier
 * @atomic: can the driver's ->apply() be called in atomic context
 * @uses_pwmchip_alloc: signals if pwmchip_allow was used to allocate this chip
 * @driver_data: Private pointer for driver specific info
 * @pwms: array of PWM devices allocated by the framework
 */
@@ -287,6 +288,7 @@ struct pwm_chip {
	bool atomic;

	/* only used internally by the PWM framework */
	bool uses_pwmchip_alloc;
	void *driver_data;
	struct pwm_device *pwms;
};