From 1271a7b98e7989ba6bb978e14403fc84efe16e13 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 22 Mar 2023 22:45:45 +0100 Subject: pwm: Zero-initialize the pwm_state passed to driver's .get_state() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is just to ensure that .usage_power is properly initialized and doesn't contain random stack data. The other members of struct pwm_state should get a value assigned in a successful call to .get_state(). So in the absence of bugs in driver implementations, this is only a safe-guard and no fix. Reported-by: Munehisa Kamata Link: https://lore.kernel.org/r/20230310214004.2619480-1-u.kleine-koenig@pengutronix.de Signed-off-by: Uwe Kleine-König Signed-off-by: Thierry Reding --- drivers/pwm/core.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/pwm/core.c') diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index e01147f66e15a..474725714a05b 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -115,7 +115,14 @@ static int pwm_device_request(struct pwm_device *pwm, const char *label) } if (pwm->chip->ops->get_state) { - struct pwm_state state; + /* + * Zero-initialize state because most drivers are unaware of + * .usage_power. The other members of state are supposed to be + * set by lowlevel drivers. We still initialize the whole + * structure for simplicity even though this might paper over + * faulty implementations of .get_state(). + */ + struct pwm_state state = { 0, }; err = pwm->chip->ops->get_state(pwm->chip, pwm, &state); trace_pwm_get(pwm, &state, err); @@ -448,7 +455,7 @@ static void pwm_apply_state_debug(struct pwm_device *pwm, { struct pwm_state *last = &pwm->last; struct pwm_chip *chip = pwm->chip; - struct pwm_state s1, s2; + struct pwm_state s1 = { 0 }, s2 = { 0 }; int err; if (!IS_ENABLED(CONFIG_PWM_DEBUG)) @@ -530,6 +537,7 @@ static void pwm_apply_state_debug(struct pwm_device *pwm, return; } + *last = (struct pwm_state){ 0 }; err = chip->ops->get_state(chip, pwm, last); trace_pwm_get(pwm, last, err); if (err) -- cgit v1.2.3 From 0af4d704ba8e5ee632b6e65015ffe4d229c1a9a9 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 12 Apr 2023 13:56:36 +0200 Subject: pwm: Delete deprecated functions pwm_request() and pwm_free() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 5a7fbe452ad9 ("backlight: pwm_bl: Drop support for legacy PWM probing") the last user of pwm_request() and pwm_free() is gone. So remove these functions that were deprecated over 10 years ago in commit 8138d2ddbcca ("pwm: Add table-based lookup for static mappings"). Signed-off-by: Uwe Kleine-König [thierry.reding@gmail.com: clean up a bit after removal] Signed-off-by: Thierry Reding --- Documentation/driver-api/pwm.rst | 13 ++++----- drivers/pwm/core.c | 58 ++-------------------------------------- include/linux/pwm.h | 13 --------- 3 files changed, 7 insertions(+), 77 deletions(-) (limited to 'drivers/pwm/core.c') diff --git a/Documentation/driver-api/pwm.rst b/Documentation/driver-api/pwm.rst index 8c71a2055d278..3fdc95f7a1d15 100644 --- a/Documentation/driver-api/pwm.rst +++ b/Documentation/driver-api/pwm.rst @@ -35,12 +35,9 @@ consumers to providers, as given in the following example:: Using PWMs ---------- -Legacy users can request a PWM device using pwm_request() and free it -after usage with pwm_free(). - -New users should use the pwm_get() function and pass to it the consumer -device or a consumer name. pwm_put() is used to free the PWM device. Managed -variants of the getter, devm_pwm_get() and devm_fwnode_pwm_get(), also exist. +Consumers use the pwm_get() function and pass to it the consumer device or a +consumer name. pwm_put() is used to free the PWM device. Managed variants of +the getter, devm_pwm_get() and devm_fwnode_pwm_get(), also exist. After being requested, a PWM has to be configured using:: @@ -165,8 +162,8 @@ consumers should implement it as described in the "Using PWMs" section. Locking ------- -The PWM core list manipulations are protected by a mutex, so pwm_request() -and pwm_free() may not be called from an atomic context. Currently the +The PWM core list manipulations are protected by a mutex, so pwm_get() +and pwm_put() may not be called from an atomic context. Currently the PWM core does not enforce any locking to pwm_enable(), pwm_disable() and pwm_config(), so the calling context is currently driver specific. This is an issue derived from the former barebone API and should be fixed soon. diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 474725714a05b..9ce85c6157e4c 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -35,11 +35,6 @@ static LIST_HEAD(pwm_chips); static DECLARE_BITMAP(allocated_pwms, MAX_PWMS); static RADIX_TREE(pwm_tree, GFP_KERNEL); -static struct pwm_device *pwm_to_device(unsigned int pwm) -{ - return radix_tree_lookup(&pwm_tree, pwm); -} - /* Called with pwm_lock held */ static int alloc_pwms(unsigned int count) { @@ -369,43 +364,6 @@ int devm_pwmchip_add(struct device *dev, struct pwm_chip *chip) } EXPORT_SYMBOL_GPL(devm_pwmchip_add); -/** - * pwm_request() - request a PWM device - * @pwm: global PWM device index - * @label: PWM device label - * - * This function is deprecated, use pwm_get() instead. - * - * Returns: A pointer to a PWM device or an ERR_PTR()-encoded error code on - * failure. - */ -struct pwm_device *pwm_request(int pwm, const char *label) -{ - struct pwm_device *dev; - int err; - - if (pwm < 0 || pwm >= MAX_PWMS) - return ERR_PTR(-EINVAL); - - mutex_lock(&pwm_lock); - - dev = pwm_to_device(pwm); - if (!dev) { - dev = ERR_PTR(-EPROBE_DEFER); - goto out; - } - - err = pwm_device_request(dev, label); - if (err < 0) - dev = ERR_PTR(err); - -out: - mutex_unlock(&pwm_lock); - - return dev; -} -EXPORT_SYMBOL_GPL(pwm_request); - /** * pwm_request_from_chip() - request a PWM device relative to a PWM chip * @chip: PWM chip @@ -438,18 +396,6 @@ struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip, } EXPORT_SYMBOL_GPL(pwm_request_from_chip); -/** - * pwm_free() - free a PWM device - * @pwm: PWM device - * - * This function is deprecated, use pwm_put() instead. - */ -void pwm_free(struct pwm_device *pwm) -{ - pwm_put(pwm); -} -EXPORT_SYMBOL_GPL(pwm_free); - static void pwm_apply_state_debug(struct pwm_device *pwm, const struct pwm_state *state) { @@ -790,7 +736,7 @@ static struct pwm_device *of_pwm_get(struct device *dev, struct device_node *np, dl = pwm_device_link_add(dev, pwm); if (IS_ERR(dl)) { /* of_xlate ended up calling pwm_request_from_chip() */ - pwm_free(pwm); + pwm_put(pwm); pwm = ERR_CAST(dl); goto put; } @@ -1014,7 +960,7 @@ struct pwm_device *pwm_get(struct device *dev, const char *con_id) dl = pwm_device_link_add(dev, pwm); if (IS_ERR(dl)) { - pwm_free(pwm); + pwm_put(pwm); return ERR_CAST(dl); } diff --git a/include/linux/pwm.h b/include/linux/pwm.h index 7b7b93b6fb81a..04ae1d9073a74 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -309,8 +309,6 @@ struct pwm_chip { #if IS_ENABLED(CONFIG_PWM) /* PWM user APIs */ -struct pwm_device *pwm_request(int pwm_id, const char *label); -void pwm_free(struct pwm_device *pwm); int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state); int pwm_adjust_config(struct pwm_device *pwm); @@ -410,17 +408,6 @@ struct pwm_device *devm_fwnode_pwm_get(struct device *dev, struct fwnode_handle *fwnode, const char *con_id); #else -static inline struct pwm_device *pwm_request(int pwm_id, const char *label) -{ - might_sleep(); - return ERR_PTR(-ENODEV); -} - -static inline void pwm_free(struct pwm_device *pwm) -{ - might_sleep(); -} - static inline int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state) { -- cgit v1.2.3 From 247ee6c780406513c6031a7f4ea41f1648b03295 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 13 Apr 2023 14:25:48 +0200 Subject: pwm: Remove unused radix tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The radix tree's only use was to map PWM channels to the global number space. With that number space gone, the radix tree is now unused, so it can simply be removed. Acked-by: Uwe Kleine-König Signed-off-by: Thierry Reding --- drivers/pwm/core.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers/pwm/core.c') diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 9ce85c6157e4c..3dacceaef4a9b 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -28,12 +28,11 @@ static DEFINE_MUTEX(pwm_lookup_lock); static LIST_HEAD(pwm_lookup_list); -/* protects access to pwm_chips, allocated_pwms, and pwm_tree */ +/* protects access to pwm_chips and allocated_pwms */ static DEFINE_MUTEX(pwm_lock); static LIST_HEAD(pwm_chips); static DECLARE_BITMAP(allocated_pwms, MAX_PWMS); -static RADIX_TREE(pwm_tree, GFP_KERNEL); /* Called with pwm_lock held */ static int alloc_pwms(unsigned int count) @@ -54,14 +53,6 @@ static int alloc_pwms(unsigned int count) /* Called with pwm_lock held */ static void free_pwms(struct pwm_chip *chip) { - unsigned int i; - - for (i = 0; i < chip->npwm; i++) { - struct pwm_device *pwm = &chip->pwms[i]; - - radix_tree_delete(&pwm_tree, pwm->pwm); - } - bitmap_clear(allocated_pwms, chip->base, chip->npwm); kfree(chip->pwms); @@ -302,8 +293,6 @@ int pwmchip_add(struct pwm_chip *chip) pwm->chip = chip; pwm->pwm = chip->base + i; pwm->hwpwm = i; - - radix_tree_insert(&pwm_tree, pwm->pwm, pwm); } list_add(&chip->list, &pwm_chips); -- cgit v1.2.3