From: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
To: Thierry Reding <thierry.reding@gmail.com>
Cc: kernel@pengutronix.de, linux-pwm@vger.kernel.org
Subject: [PATCH v4 112/115] pwm: Ensure the memory backing a PWM chip isn't freed while used
Date: Wed, 6 Dec 2023 12:45:06 +0100 [thread overview]
Message-ID: <80bb35a80318e2f23345fbbd473206cef8613582.1701860672.git.u.kleine-koenig@pengutronix.de> (raw)
In-Reply-To: <cover.1701860672.git.u.kleine-koenig@pengutronix.de>
The memory allocated to hold a struct pwm_chip is tied now to the struct
device that is added to struct pwm_chip. This way it's only freed when
the last reference is dropped.
Currently this isn't required yet as device links make sure that a
consumer is gone before the PWM chip goes away. However there are plans
to introduce character device support for PWM chips and with that in
place it can happen that a reference to a pwm_chip is held with its
driver going away.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
drivers/pwm/Kconfig | 4 --
drivers/pwm/Makefile | 3 +-
drivers/pwm/core.c | 127 +++++++++++++++++++++++++++++++------------
drivers/pwm/sysfs.c | 45 +++------------
include/linux/pwm.h | 17 ++----
5 files changed, 105 insertions(+), 91 deletions(-)
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 4b956d661755..1dd7921194f5 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -29,10 +29,6 @@ menuconfig PWM
if PWM
-config PWM_SYSFS
- bool
- default y if SYSFS
-
config PWM_DEBUG
bool "PWM lowlevel drivers additional checks and debug messages"
depends on DEBUG_KERNEL
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index c5ec9e168ee7..2aaaf92a7035 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -1,6 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_PWM) += core.o
-obj-$(CONFIG_PWM_SYSFS) += sysfs.o
+obj-$(CONFIG_PWM) += core.o sysfs.o
obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o
obj-$(CONFIG_PWM_APPLE) += pwm-apple.o
obj-$(CONFIG_PWM_ATMEL) += pwm-atmel.o
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index b3ba08aa0b14..4805ccff5970 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -43,7 +43,7 @@ static struct pwm_chip *pwmchip_find_by_name(const char *name)
mutex_lock(&pwm_lock);
idr_for_each_entry_ul(&pwmchip_idr, chip, tmp, id) {
- const char *chip_name = dev_name(chip->dev);
+ const char *chip_name = dev_name(chip->dev.parent);
if (chip_name && strcmp(chip_name, name) == 0) {
mutex_unlock(&pwm_lock);
@@ -65,13 +65,13 @@ static int pwm_device_request(struct pwm_device *pwm, const char *label)
if (test_bit(PWMF_REQUESTED, &pwm->flags))
return -EBUSY;
- if (!try_module_get(chip->owner))
+ if (!get_device(&chip->dev))
return -ENODEV;
if (ops->request) {
err = ops->request(chip, pwm);
if (err) {
- module_put(chip->owner);
+ put_device(&chip->dev);
return err;
}
}
@@ -161,13 +161,13 @@ EXPORT_SYMBOL_GPL(of_pwm_single_xlate);
static void of_pwmchip_add(struct pwm_chip *chip)
{
- if (!chip->dev || !chip->dev->of_node)
+ if (!chip->dev.parent || !chip->dev.parent->of_node)
return;
if (!chip->of_xlate) {
u32 pwm_cells;
- if (of_property_read_u32(chip->dev->of_node, "#pwm-cells",
+ if (of_property_read_u32(chip->dev.parent->of_node, "#pwm-cells",
&pwm_cells))
pwm_cells = 2;
@@ -175,13 +175,13 @@ static void of_pwmchip_add(struct pwm_chip *chip)
chip->of_pwm_n_cells = pwm_cells;
}
- of_node_get(chip->dev->of_node);
+ of_node_get(chip->dev.parent->of_node);
}
static void of_pwmchip_remove(struct pwm_chip *chip)
{
- if (chip->dev)
- of_node_put(chip->dev->of_node);
+ if (chip->dev.parent)
+ of_node_put(chip->dev.parent->of_node);
}
static bool pwm_ops_check(const struct pwm_chip *chip)
@@ -192,7 +192,7 @@ static bool pwm_ops_check(const struct pwm_chip *chip)
return false;
if (IS_ENABLED(CONFIG_PWM_DEBUG) && !ops->get_state)
- dev_warn(chip->dev,
+ dev_warn(chip->dev.parent,
"Please implement the .get_state() callback\n");
return true;
@@ -203,19 +203,33 @@ static void *pwmchip_priv(struct pwm_chip *chip)
return (void *)chip + struct_size(chip, pwms, chip->npwm);
}
-struct pwm_chip *devm_pwmchip_alloc(struct device *parent, unsigned int npwm, size_t sizeof_priv)
+static void pwmchip_release(struct device *dev)
+{
+ struct pwm_chip *chip = container_of(dev, struct pwm_chip, dev);
+
+ kfree(chip);
+}
+
+static struct pwm_chip *pwmchip_alloc(struct device *parent, unsigned int npwm, size_t sizeof_priv)
{
struct pwm_chip *chip;
+ struct device *dev;
size_t alloc_size;
unsigned int i;
alloc_size = size_add(struct_size(chip, pwms, npwm), sizeof_priv);
- chip = devm_kzalloc(parent, alloc_size, GFP_KERNEL);
+ chip = kzalloc(alloc_size, GFP_KERNEL);
if (!chip)
return ERR_PTR(-ENOMEM);
- chip->dev = parent;
+ dev = &chip->dev;
+
+ device_initialize(dev);
+ dev->class = &pwm_class;
+ dev->parent = parent;
+ dev->release = pwmchip_release;
+
chip->npwm = npwm;
chip->uses_pwmchip_alloc = true;
@@ -230,6 +244,29 @@ struct pwm_chip *devm_pwmchip_alloc(struct device *parent, unsigned int npwm, si
return chip;
}
+
+static void devm_pwmchip_put(void *_chip)
+{
+ struct pwm_chip *chip = _chip;
+
+ put_device(&chip->dev);
+}
+
+struct pwm_chip *devm_pwmchip_alloc(struct device *parent, unsigned int npwm, size_t sizeof_priv)
+{
+ struct pwm_chip *chip;
+ int ret;
+
+ chip = pwmchip_alloc(parent, npwm, sizeof_priv);
+ if (IS_ERR(chip))
+ return chip;
+
+ ret = devm_add_action_or_reset(parent, devm_pwmchip_put, chip);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return chip;
+}
EXPORT_SYMBOL_GPL(devm_pwmchip_alloc);
/**
@@ -246,7 +283,7 @@ int __pwmchip_add(struct pwm_chip *chip, struct module *owner)
{
int ret;
- if (!chip || !chip->dev || !chip->ops || !chip->npwm)
+ if (!chip || !chip->dev.parent || !chip->ops || !chip->npwm)
return -EINVAL;
/*
@@ -262,25 +299,41 @@ int __pwmchip_add(struct pwm_chip *chip, struct module *owner)
return -EINVAL;
chip->owner = owner;
+ if (!try_module_get(owner))
+ return -EINVAL;
mutex_lock(&pwm_lock);
ret = idr_alloc(&pwmchip_idr, chip, 0, 0, GFP_KERNEL);
- if (ret < 0) {
- mutex_unlock(&pwm_lock);
- return ret;
- }
+ if (ret < 0)
+ goto err_idr_alloc;
chip->id = ret;
-
- mutex_unlock(&pwm_lock);
+ dev_set_name(&chip->dev, "pwmchip%u", chip->id);
if (IS_ENABLED(CONFIG_OF))
of_pwmchip_add(chip);
- pwmchip_sysfs_export(chip);
+ ret = device_add(&chip->dev);
+ if (ret)
+ goto err_device_add;
+
+ mutex_unlock(&pwm_lock);
return 0;
+
+err_device_add:
+
+ if (IS_ENABLED(CONFIG_OF))
+ of_pwmchip_remove(chip);
+
+ idr_remove(&pwmchip_idr, chip->id);
+err_idr_alloc:
+
+ mutex_unlock(&pwm_lock);
+ module_put(owner);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(__pwmchip_add);
@@ -302,6 +355,10 @@ void pwmchip_remove(struct pwm_chip *chip)
idr_remove(&pwmchip_idr, chip->id);
mutex_unlock(&pwm_lock);
+
+ module_put(chip->owner);
+
+ device_del(&chip->dev);
}
EXPORT_SYMBOL_GPL(pwmchip_remove);
@@ -398,18 +455,18 @@ static void pwm_apply_state_debug(struct pwm_device *pwm,
if (s2.polarity != state->polarity &&
state->duty_cycle < state->period)
- dev_warn(chip->dev, ".apply ignored .polarity\n");
+ dev_warn(chip->dev.parent, ".apply ignored .polarity\n");
if (state->enabled &&
last->polarity == state->polarity &&
last->period > s2.period &&
last->period <= state->period)
- dev_warn(chip->dev,
+ dev_warn(chip->dev.parent,
".apply didn't pick the best available period (requested: %llu, applied: %llu, possible: %llu)\n",
state->period, s2.period, last->period);
if (state->enabled && state->period < s2.period)
- dev_warn(chip->dev,
+ dev_warn(chip->dev.parent,
".apply is supposed to round down period (requested: %llu, applied: %llu)\n",
state->period, s2.period);
@@ -418,20 +475,20 @@ static void pwm_apply_state_debug(struct pwm_device *pwm,
last->period == s2.period &&
last->duty_cycle > s2.duty_cycle &&
last->duty_cycle <= state->duty_cycle)
- dev_warn(chip->dev,
+ dev_warn(chip->dev.parent,
".apply didn't pick the best available duty cycle (requested: %llu/%llu, applied: %llu/%llu, possible: %llu/%llu)\n",
state->duty_cycle, state->period,
s2.duty_cycle, s2.period,
last->duty_cycle, last->period);
if (state->enabled && state->duty_cycle < s2.duty_cycle)
- dev_warn(chip->dev,
+ dev_warn(chip->dev.parent,
".apply is supposed to round down duty_cycle (requested: %llu/%llu, applied: %llu/%llu)\n",
state->duty_cycle, state->period,
s2.duty_cycle, s2.period);
if (!state->enabled && s2.enabled && s2.duty_cycle > 0)
- dev_warn(chip->dev,
+ dev_warn(chip->dev.parent,
"requested disabled, but yielded enabled with duty > 0\n");
/* reapply the state that the driver reported being configured. */
@@ -439,7 +496,7 @@ static void pwm_apply_state_debug(struct pwm_device *pwm,
trace_pwm_apply(pwm, &s1, err);
if (err) {
*last = s1;
- dev_err(chip->dev, "failed to reapply current setting\n");
+ dev_err(&chip->dev, "failed to reapply current setting\n");
return;
}
@@ -454,7 +511,7 @@ static void pwm_apply_state_debug(struct pwm_device *pwm,
s1.polarity != last->polarity ||
(s1.enabled && s1.period != last->period) ||
(s1.enabled && s1.duty_cycle != last->duty_cycle)) {
- dev_err(chip->dev,
+ dev_err(&chip->dev,
".apply is not idempotent (ena=%d pol=%d %llu/%llu) -> (ena=%d pol=%d %llu/%llu)\n",
s1.enabled, s1.polarity, s1.duty_cycle, s1.period,
last->enabled, last->polarity, last->duty_cycle,
@@ -602,7 +659,7 @@ static struct pwm_chip *fwnode_to_pwmchip(struct fwnode_handle *fwnode)
mutex_lock(&pwm_lock);
idr_for_each_entry_ul(&pwmchip_idr, chip, tmp, id)
- if (chip->dev && device_match_fwnode(chip->dev, fwnode)) {
+ if (device_match_fwnode(chip->dev.parent, fwnode)) {
mutex_unlock(&pwm_lock);
return chip;
}
@@ -623,15 +680,15 @@ static struct device_link *pwm_device_link_add(struct device *dev,
* impact the PM sequence ordering: the PWM supplier may get
* suspended before the consumer.
*/
- dev_warn(pwm->chip->dev,
+ dev_warn(&pwm->chip->dev,
"No consumer device specified to create a link to\n");
return NULL;
}
- dl = device_link_add(dev, pwm->chip->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
+ dl = device_link_add(dev, pwm->chip->dev.parent, DL_FLAG_AUTOREMOVE_CONSUMER);
if (!dl) {
dev_err(dev, "failed to create device link to %s\n",
- dev_name(pwm->chip->dev));
+ dev_name(pwm->chip->dev.parent));
return ERR_PTR(-EINVAL);
}
@@ -953,7 +1010,7 @@ void pwm_put(struct pwm_device *pwm)
pwm->label = NULL;
- module_put(pwm->chip->owner);
+ put_device(&pwm->chip->dev);
out:
mutex_unlock(&pwm_lock);
}
@@ -1093,8 +1150,8 @@ static int pwm_seq_show(struct seq_file *s, void *v)
seq_printf(s, "%s%d: %s/%s, %d PWM device%s\n",
(char *)s->private, chip->id,
- chip->dev->bus ? chip->dev->bus->name : "no-bus",
- dev_name(chip->dev), chip->npwm,
+ chip->dev.parent->bus ? chip->dev.parent->bus->name : "no-bus",
+ dev_name(chip->dev.parent), chip->npwm,
(chip->npwm != 1) ? "s" : "");
pwm_dbg_show(chip, s);
diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c
index 4edb994fa2e1..3a438b29c777 100644
--- a/drivers/pwm/sysfs.c
+++ b/drivers/pwm/sysfs.c
@@ -311,7 +311,7 @@ static ssize_t export_store(struct device *parent,
struct device_attribute *attr,
const char *buf, size_t len)
{
- struct pwm_chip *chip = dev_get_drvdata(parent);
+ struct pwm_chip *chip = container_of(parent, struct pwm_chip, dev);
struct pwm_device *pwm;
unsigned int hwpwm;
int ret;
@@ -339,7 +339,7 @@ static ssize_t unexport_store(struct device *parent,
struct device_attribute *attr,
const char *buf, size_t len)
{
- struct pwm_chip *chip = dev_get_drvdata(parent);
+ struct pwm_chip *chip = container_of(parent, struct pwm_chip, dev);
unsigned int hwpwm;
int ret;
@@ -359,7 +359,7 @@ static DEVICE_ATTR_WO(unexport);
static ssize_t npwm_show(struct device *parent, struct device_attribute *attr,
char *buf)
{
- const struct pwm_chip *chip = dev_get_drvdata(parent);
+ const struct pwm_chip *chip = container_of(parent, struct pwm_chip, dev);
return sysfs_emit(buf, "%u\n", chip->npwm);
}
@@ -411,7 +411,7 @@ static int pwm_class_apply_state(struct pwm_export *export,
static int pwm_class_resume_npwm(struct device *parent, unsigned int npwm)
{
- struct pwm_chip *chip = dev_get_drvdata(parent);
+ struct pwm_chip *chip = container_of(parent, struct pwm_chip, dev);
unsigned int i;
int ret = 0;
@@ -442,7 +442,7 @@ static int pwm_class_resume_npwm(struct device *parent, unsigned int npwm)
static int pwm_class_suspend(struct device *parent)
{
- struct pwm_chip *chip = dev_get_drvdata(parent);
+ struct pwm_chip *chip = container_of(parent, struct pwm_chip, dev);
unsigned int i;
int ret = 0;
@@ -483,59 +483,30 @@ static int pwm_class_suspend(struct device *parent)
static int pwm_class_resume(struct device *parent)
{
- struct pwm_chip *chip = dev_get_drvdata(parent);
+ struct pwm_chip *chip = container_of(parent, struct pwm_chip, dev);
return pwm_class_resume_npwm(parent, chip->npwm);
}
static DEFINE_SIMPLE_DEV_PM_OPS(pwm_class_pm_ops, pwm_class_suspend, pwm_class_resume);
-static struct class pwm_class = {
+struct class pwm_class = {
.name = "pwm",
.dev_groups = pwm_chip_groups,
.pm = pm_sleep_ptr(&pwm_class_pm_ops),
};
-static int pwmchip_sysfs_match(struct device *parent, const void *data)
-{
- return dev_get_drvdata(parent) == data;
-}
-
-void pwmchip_sysfs_export(struct pwm_chip *chip)
-{
- struct device *parent;
-
- /*
- * If device_create() fails the pwm_chip is still usable by
- * the kernel it's just not exported.
- */
- parent = device_create(&pwm_class, chip->dev, MKDEV(0, 0), chip,
- "pwmchip%d", chip->id);
- if (IS_ERR(parent)) {
- dev_warn(chip->dev,
- "device_create failed for pwm_chip sysfs export\n");
- }
-}
-
void pwmchip_sysfs_unexport(struct pwm_chip *chip)
{
- struct device *parent;
+ struct device *parent = &chip->dev;
unsigned int i;
- parent = class_find_device(&pwm_class, NULL, chip,
- pwmchip_sysfs_match);
- if (!parent)
- return;
-
for (i = 0; i < chip->npwm; i++) {
struct pwm_device *pwm = &chip->pwms[i];
if (test_bit(PWMF_EXPORTED, &pwm->flags))
pwm_unexport_child(parent, pwm);
}
-
- put_device(parent);
- device_unregister(parent);
}
static int __init pwm_sysfs_init(void)
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index eb91306ba28e..8b4aca36c35f 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -2,6 +2,7 @@
#ifndef __LINUX_PWM_H
#define __LINUX_PWM_H
+#include <linux/device.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/of.h>
@@ -289,7 +290,7 @@ struct pwm_ops {
* @pwms: array of PWM devices allocated by the framework
*/
struct pwm_chip {
- struct device *dev;
+ struct device dev;
const struct pwm_ops *ops;
struct module *owner;
unsigned int id;
@@ -307,7 +308,7 @@ struct pwm_chip {
static inline struct device *pwmchip_parent(struct pwm_chip *chip)
{
- return chip->dev;
+ return chip->dev.parent;
}
static inline void *pwmchip_get_drvdata(struct pwm_chip *chip)
@@ -592,17 +593,7 @@ static inline void pwm_remove_table(struct pwm_lookup *table, size_t num)
}
#endif
-#ifdef CONFIG_PWM_SYSFS
-void pwmchip_sysfs_export(struct pwm_chip *chip);
+extern struct class pwm_class;
void pwmchip_sysfs_unexport(struct pwm_chip *chip);
-#else
-static inline void pwmchip_sysfs_export(struct pwm_chip *chip)
-{
-}
-
-static inline void pwmchip_sysfs_unexport(struct pwm_chip *chip)
-{
-}
-#endif /* CONFIG_PWM_SYSFS */
#endif /* __LINUX_PWM_H */
--
2.42.0
next prev parent reply other threads:[~2023-12-06 11:48 UTC|newest]
Thread overview: 127+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-12-06 11:43 [PATCH v4 000/115] pwm: Fix lifetime issues for pwm_chips Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 001/115] pwm: Reduce number of pointer dereferences in pwm_device_request() Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 002/115] pwm: crc: Use consistent variable naming for driver data Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 006/115] pwm: cros-ec: Change prototype of helpers to prepare further changes Uwe Kleine-König
2023-12-07 2:06 ` Tzung-Bi Shih
2023-12-06 11:43 ` [PATCH v4 007/115] pwm: Provide a macro to get the parent device of a given chip Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 008/115] pwm: ab8500: Make use of pwmchip_parent() macro Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 009/115] pwm: atmel: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 010/115] pwm: atmel-tcb: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 011/115] pwm: bcm-kona: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 012/115] pwm: crc: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 013/115] pwm: cros-ec: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 014/115] pwm: dwc: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 015/115] pwm: ep93xx: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 016/115] pwm: fsl-ftm: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 017/115] pwm: img: Make use of parent device pointer in driver data Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 018/115] pwm: imx27: Make use of pwmchip_parent() macro Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 019/115] pwm: jz4740: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 020/115] pwm: lpc18xx-sct: Make use of parent device pointer in driver data Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 021/115] pwm: lpss: Make use of pwmchip_parent() macro Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 022/115] pwm: mediatek: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 023/115] pwm: meson: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 024/115] pwm: mtk-disp: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 025/115] pwm: omap: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 026/115] pwm: pca9685: Store parent device in driver data Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 027/115] pwm: raspberrypi-poe: Make use of pwmchip_parent() macro Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 028/115] pwm: rcar: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 029/115] pwm: rz-mtu3: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 030/115] pwm: samsung: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 031/115] pwm: sifive: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 032/115] pwm: stm32-lp: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 033/115] pwm: stm32: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 034/115] pwm: stmpe: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 035/115] pwm: sun4i: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 036/115] pwm: tiecap: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 037/115] pwm: tiehrpwm: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 038/115] pwm: twl-led: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 039/115] pwm: twl: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 040/115] pwm: vt8500: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 041/115] staging: greybus: pwm: " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 042/115] pwm: Provide wrappers for storing and getting driver private data Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 043/115] pwm: Provide devm_pwmchip_alloc() function Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 044/115] pwm: ab8500: Make use of " Uwe Kleine-König
2023-12-06 11:43 ` [PATCH v4 045/115] pwm: apple: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 046/115] pwm: atmel-hlcdc: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 047/115] pwm: atmel: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 048/115] pwm: atmel-tcb: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 049/115] pwm: bcm2835: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 050/115] pwm: bcm-iproc: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 051/115] pwm: bcm-kona: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 052/115] pwm: berlin: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 053/115] pwm: brcmstb: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 054/115] pwm: clk: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 055/115] pwm: clps711x: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 056/115] pwm: crc: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 057/115] pwm: cros-ec: " Uwe Kleine-König
2023-12-07 2:07 ` Tzung-Bi Shih
2023-12-06 11:44 ` [PATCH v4 058/115] pwm: dwc: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 059/115] pwm: ep93xx: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 060/115] pwm: fsl-ftm: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 061/115] pwm: hibvt: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 062/115] pwm: img: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 063/115] pwm: imx1: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 064/115] pwm: imx27: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 065/115] pwm: imx-tpm: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 066/115] pwm: intel-lgm: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 067/115] pwm: iqs620a: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 068/115] pwm: jz4740: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 069/115] pwm: keembay: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 070/115] pwm: lp3943: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 071/115] pwm: lpc18xx-sct: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 072/115] pwm: lpc32xx: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 073/115] pwm: lpss-*: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 074/115] pwm: mediatek: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 075/115] pwm: meson: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 076/115] pwm: microchip-core: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 077/115] pwm: mtk-disp: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 078/115] pwm: mxs: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 079/115] pwm: ntxec: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 080/115] pwm: omap-dmtimer: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 081/115] pwm: pca9685: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 082/115] pwm: pxa: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 083/115] pwm: raspberrypi-poe: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 084/115] pwm: rcar: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 085/115] pwm: renesas-tpu: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 086/115] pwm: rockchip: " Uwe Kleine-König
2023-12-06 13:06 ` Heiko Stübner
2023-12-06 11:44 ` [PATCH v4 087/115] pwm: rz-mtu3: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 088/115] pwm: samsung: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 089/115] pwm: sifive: " Uwe Kleine-König
2023-12-08 9:30 ` Emil Renner Berthing
2023-12-08 9:52 ` Uwe Kleine-König
2023-12-08 9:59 ` Emil Renner Berthing
2023-12-06 11:44 ` [PATCH v4 090/115] pwm: sl28cpld: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 091/115] pwm: spear: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 092/115] pwm: sprd: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 093/115] pwm: sti: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 094/115] pwm: stm32-lp: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 095/115] pwm: stm32: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 096/115] pwm: stmpe: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 097/115] pwm: sun4i: " Uwe Kleine-König
2023-12-06 17:11 ` Andre Przywara
2023-12-13 20:31 ` Jernej Škrabec
2023-12-06 11:44 ` [PATCH v4 098/115] pwm: sunplus: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 099/115] pwm: tegra: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 100/115] pwm: tiecap: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 101/115] pwm: twl-led: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 102/115] pwm: twl: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 103/115] pwm: visconti: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 104/115] pwm: vt8500: " Uwe Kleine-König
2023-12-06 11:44 ` [PATCH v4 105/115] pwm: xilinx: " Uwe Kleine-König
2023-12-06 11:45 ` [PATCH v4 106/115] gpio: mvebu: " Uwe Kleine-König
2023-12-06 11:45 ` [PATCH v4 107/115] drm/bridge: ti-sn65dsi86: " Uwe Kleine-König
2024-01-22 15:19 ` Robert Foss
2023-12-06 11:45 ` [PATCH v4 108/115] leds: qcom-lpg: " Uwe Kleine-König
2023-12-07 17:05 ` Lee Jones
2023-12-06 11:45 ` [PATCH v4 110/115] pwm: Ensure that pwm_chips are allocated using pwmchip_alloc() Uwe Kleine-König
2023-12-06 11:45 ` [PATCH v4 111/115] pwm: Ensure a struct pwm has the same lifetime as its pwm_chip Uwe Kleine-König
2023-12-06 11:45 ` Uwe Kleine-König [this message]
2023-12-06 11:45 ` [PATCH v4 113/115] pwm: Add more locking Uwe Kleine-König
2023-12-06 11:45 ` [PATCH v4 114/115] pwm: Make pwmchip_[sg]et_drvdata a wrapper around dev_set_drvdata Uwe Kleine-König
2023-12-06 11:45 ` [PATCH v4 115/115] WIP: pwm: Add support for pwmchip devices for faster and easier userspace access Uwe Kleine-König
2023-12-08 15:41 ` [PATCH v4 000/115] pwm: Fix lifetime issues for pwm_chips Thierry Reding
2023-12-08 18:50 ` Uwe Kleine-König
2023-12-11 11:33 ` Thierry Reding
2023-12-11 12:18 ` Uwe Kleine-König
2023-12-12 21:05 ` Uwe Kleine-König
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=80bb35a80318e2f23345fbbd473206cef8613582.1701860672.git.u.kleine-koenig@pengutronix.de \
--to=u.kleine-koenig@pengutronix.de \
--cc=kernel@pengutronix.de \
--cc=linux-pwm@vger.kernel.org \
--cc=thierry.reding@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).