@@ -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;
@@ -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;
};
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/89afb1f6191aff726f537b5d450cc74f90236ea4.1706182805.git.u.kleine-koenig@pengutronix.de Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> --- drivers/pwm/core.c | 10 ++++++++++ include/linux/pwm.h | 2 ++ 2 files changed, 12 insertions(+)