mbox series

[v1,000/101] pwm: Fix lifetime issues for pwm_chips

Message ID 20230808171931.944154-1-u.kleine-koenig@pengutronix.de
Headers show
Series pwm: Fix lifetime issues for pwm_chips | expand

Message

Uwe Kleine-König Aug. 8, 2023, 5:17 p.m. UTC
Hello,

this series addresses the issues I reported already earlier to this
list[1]. It is based on pwm/for-next and several patches I already sent
out, too. Maybe some of these have to be reworked (e.g. Thierry already
signalled not to like the patches dropping runtime error messages) but
in the expectation that I will have to create a v2 for this series, too
and it actually fixes a race condition, I sent the patches out for
review anyhow. For the same reason I didn't Cc: all the individual
maintainers.

If you want to actually test I suggest you fetch my complete history
from

	https://git.pengutronix.de/git/ukl/linux pwm-lifetime-tracking

. 

In the end drivers have to allocate their pwm_chip using
pwmchip_alloc(). This is important for the memory backing the pwm_chip
being able to have a longer life than the driver.

The motivation for this series is to prepare the pwm framework to add a
character device for each pwm_chip for easier and faster access to PWMs
from userspace compared to the sysfs API. For such an extension proper
lifetime tracking is important, too, as such a device can still be open
if a PWM disappears.

Have fun
Uwe

[1] https://lore.kernel.org/linux-pwm/20230725211004.peqxxb4y3j62gmnp@pengutronix.de/

Uwe Kleine-König (101):
  pwm: Provide devm_pwmchip_alloc() function
  pwm: ab8500: Make use of devm_pwmchip_alloc() function
  pwm: apple: Make use of devm_pwmchip_alloc() function
  pwm: atmel-hlcdc: Make use of devm_pwmchip_alloc() function
  pwm: atmel: Make use of devm_pwmchip_alloc() function
  pwm: atmel-tcb: Make use of devm_pwmchip_alloc() function
  pwm: bcm2835: Make use of devm_pwmchip_alloc() function
  pwm: bcm-iproc: Make use of devm_pwmchip_alloc() function
  pwm: bcm-kona: Make use of devm_pwmchip_alloc() function
  pwm: berlin: Make use of devm_pwmchip_alloc() function
  pwm: brcmstb: Make use of devm_pwmchip_alloc() function
  pwm: clk: Make use of devm_pwmchip_alloc() function
  pwm: clps711x: Make use of devm_pwmchip_alloc() function
  pwm: crc: Make use of devm_pwmchip_alloc() function
  pwm: cros-ec: Change prototype of helper to prepare further changes
  pwm: cros-ec: Make use of devm_pwmchip_alloc() function
  pwm: dwc: Make use of devm_pwmchip_alloc() function
  pwm: ep93xx: Make use of devm_pwmchip_alloc() function
  pwm: fsl-ftm: Make use of devm_pwmchip_alloc() function
  pwm: hibvt: Make use of devm_pwmchip_alloc() function
  pwm: img: Make use of devm_pwmchip_alloc() function
  pwm: imx1: Make use of devm_pwmchip_alloc() function
  pwm: imx27: Make use of devm_pwmchip_alloc() function
  pwm: imx-tpm: Make use of devm_pwmchip_alloc() function
  pwm: intel-lgm: Make use of devm_pwmchip_alloc() function
  pwm: iqs620a: Make use of devm_pwmchip_alloc() function
  pwm: jz4740: Make use of devm_pwmchip_alloc() function
  pwm: keembay: Make use of devm_pwmchip_alloc() function
  pwm: lp3943: Make use of devm_pwmchip_alloc() function
  pwm: lpc18xx-sct: Make use of devm_pwmchip_alloc() function
  pwm: lpc32xx: Make use of devm_pwmchip_alloc() function
  pwm: lpss-*: Make use of devm_pwmchip_alloc() function
  pwm: mediatek: Make use of devm_pwmchip_alloc() function
  pwm: meson: Make use of devm_pwmchip_alloc() function
  pwm: microchip-core: Make use of devm_pwmchip_alloc() function
  pwm: mtk-disp: Make use of devm_pwmchip_alloc() function
  pwm: mxs: Make use of devm_pwmchip_alloc() function
  pwm: ntxec: Make use of devm_pwmchip_alloc() function
  pwm: omap-dmtimer: Make use of devm_pwmchip_alloc() function
  pwm: pca9685: Make use of devm_pwmchip_alloc() function
  pwm: pxa: Make use of devm_pwmchip_alloc() function
  pwm: raspberrypi-poe: Make use of devm_pwmchip_alloc() function
  pwm: rcar: Make use of devm_pwmchip_alloc() function
  pwm: renesas-tpu: Make use of devm_pwmchip_alloc() function
  pwm: rockchip: Make use of devm_pwmchip_alloc() function
  pwm: rz-mtu3: Make use of devm_pwmchip_alloc() function
  pwm: samsung: Make use of devm_pwmchip_alloc() function
  pwm: sifive: Make use of devm_pwmchip_alloc() function
  pwm: sl28cpld: Make use of devm_pwmchip_alloc() function
  pwm: spear: Make use of devm_pwmchip_alloc() function
  pwm: sprd: Make use of devm_pwmchip_alloc() function
  pwm: sti: Make use of devm_pwmchip_alloc() function
  pwm: stm32-lp: Make use of devm_pwmchip_alloc() function
  pwm: stm32: Make use of devm_pwmchip_alloc() function
  pwm: stmpe: Make use of devm_pwmchip_alloc() function
  pwm: sun4i: Make use of devm_pwmchip_alloc() function
  pwm: sunplus: Make use of devm_pwmchip_alloc() function
  pwm: tegra: Make use of devm_pwmchip_alloc() function
  pwm: tiecap: Make use of devm_pwmchip_alloc() function
  pwm: tiehrpwm: Make use of devm_pwmchip_alloc() function
  pwm: twl-led: Make use of devm_pwmchip_alloc() function
  pwm: twl: Make use of devm_pwmchip_alloc() function
  pwm: visconti: Make use of devm_pwmchip_alloc() function
  pwm: vt8500: Make use of devm_pwmchip_alloc() function
  pwm: xilinx: Make use of devm_pwmchip_alloc() function
  gpio: mvebu: Make use of devm_pwmchip_alloc() function
  drm/bridge: ti-sn65dsi86: Make use of devm_pwmchip_alloc() function
  leds: qcom-lpg: Make use of devm_pwmchip_alloc() function
  staging: greybus: pwm: Make use of devm_pwmchip_alloc() function
  pwm: Ensure a struct pwm have the same lifetime as its pwm_chip
  pwm: ab8500: Store parent device in driver data
  pwm: atmel: Stop using struct pwm_chip::dev
  pwm: dwc: Store parent device in driver data
  pwm: ep93xx: Store parent device in driver data
  pwm: fsl-ftm: Store parent device in driver data
  pwm: img: Make use of parent device pointer in driver data
  pwm: imx27: Store parent device in driver data
  pwm: jz4740: Store parent device in driver data
  pwm: lpc18xx-sct: Make use of parent device pointer in driver data
  pwm: lpss: Store parent device in driver data
  pwm: mediatek: Store parent device in driver data
  pwm: meson: Store parent device in driver data
  pwm: mtk-disp: Store parent device in driver data
  pwm: omap: Store parent device in driver data
  pwm: pca9685: Store parent device in driver data
  pwm: raspberrypi-poe: Store parent device in driver data
  pwm: rcar: Store parent device in driver data
  pwm: rz-mtu3: Make use of parent device pointer in driver data
  pwm: samsung: Store parent device in driver data
  pwm: sifive: Make use of parent device pointer in driver data
  pwm: stm32: Store parent device in driver data
  pwm: stmpe: Store parent device in driver data
  pwm: sun4i: Store parent device in driver data
  pwm: tiecap: Store parent device in driver data
  pwm: tiehrpwm: Store parent device in driver data
  pwm: twl: Store parent device in driver data
  pwm: twl-led: Store parent device in driver data
  pwm: vt8500: Store parent device in driver data
  staging: greybus: pwm: Store parent device in driver data
  pwm: Ensure the memory backing a PWM chip isn't freed while used
  pwm: Add more locking

 .../driver-api/driver-model/devres.rst        |   1 +
 Documentation/driver-api/pwm.rst              |  10 +-
 drivers/gpio/gpio-mvebu.c                     |  18 +-
 drivers/gpu/drm/bridge/ti-sn65dsi86.c         |  25 ++-
 drivers/leds/rgb/leds-qcom-lpg.c              |  30 ++-
 drivers/pwm/Kconfig                           |   4 -
 drivers/pwm/Makefile                          |   3 +-
 drivers/pwm/core.c                            | 208 +++++++++++++-----
 drivers/pwm/pwm-ab8500.c                      |  34 +--
 drivers/pwm/pwm-apple.c                       |  18 +-
 drivers/pwm/pwm-atmel-hlcdc.c                 |  35 +--
 drivers/pwm/pwm-atmel-tcb.c                   |  24 +-
 drivers/pwm/pwm-atmel.c                       |  31 ++-
 drivers/pwm/pwm-bcm-iproc.c                   |  19 +-
 drivers/pwm/pwm-bcm-kona.c                    |  17 +-
 drivers/pwm/pwm-bcm2835.c                     |  17 +-
 drivers/pwm/pwm-berlin.c                      |  29 +--
 drivers/pwm/pwm-brcmstb.c                     |  17 +-
 drivers/pwm/pwm-clk.c                         |  27 ++-
 drivers/pwm/pwm-clps711x.c                    |  21 +-
 drivers/pwm/pwm-crc.c                         |  23 +-
 drivers/pwm/pwm-cros-ec.c                     |  49 ++---
 drivers/pwm/pwm-dwc.c                         |  54 +++--
 drivers/pwm/pwm-ep93xx.c                      |  28 +--
 drivers/pwm/pwm-fsl-ftm.c                     |  50 +++--
 drivers/pwm/pwm-hibvt.c                       |  25 ++-
 drivers/pwm/pwm-img.c                         |  51 ++---
 drivers/pwm/pwm-imx-tpm.c                     |  34 +--
 drivers/pwm/pwm-imx1.c                        |  17 +-
 drivers/pwm/pwm-imx27.c                       |  28 ++-
 drivers/pwm/pwm-intel-lgm.c                   |  17 +-
 drivers/pwm/pwm-iqs620a.c                     |  37 ++--
 drivers/pwm/pwm-jz4740.c                      |  38 ++--
 drivers/pwm/pwm-keembay.c                     |  17 +-
 drivers/pwm/pwm-lp3943.c                      |  17 +-
 drivers/pwm/pwm-lpc18xx-sct.c                 |  29 ++-
 drivers/pwm/pwm-lpc32xx.c                     |  19 +-
 drivers/pwm/pwm-lpss-pci.c                    |  10 +-
 drivers/pwm/pwm-lpss-platform.c               |  10 +-
 drivers/pwm/pwm-lpss.c                        |  36 +--
 drivers/pwm/pwm-lpss.h                        |   2 +-
 drivers/pwm/pwm-mediatek.c                    |  30 +--
 drivers/pwm/pwm-meson.c                       |  59 ++---
 drivers/pwm/pwm-microchip-core.c              |  17 +-
 drivers/pwm/pwm-mtk-disp.c                    |  27 +--
 drivers/pwm/pwm-mxs.c                         |  32 +--
 drivers/pwm/pwm-ntxec.c                       |  30 ++-
 drivers/pwm/pwm-omap-dmtimer.c                |  48 ++--
 drivers/pwm/pwm-pca9685.c                     |  44 ++--
 drivers/pwm/pwm-pxa.c                         |  21 +-
 drivers/pwm/pwm-raspberrypi-poe.c             |  22 +-
 drivers/pwm/pwm-rcar.c                        |  28 +--
 drivers/pwm/pwm-renesas-tpu.c                 |  18 +-
 drivers/pwm/pwm-rockchip.c                    |  24 +-
 drivers/pwm/pwm-rz-mtu3.c                     |  35 +--
 drivers/pwm/pwm-samsung.c                     |  56 ++---
 drivers/pwm/pwm-sifive.c                      |  30 +--
 drivers/pwm/pwm-sl28cpld.c                    |  13 +-
 drivers/pwm/pwm-spear.c                       |  17 +-
 drivers/pwm/pwm-sprd.c                        |  50 ++---
 drivers/pwm/pwm-sti.c                         |  34 +--
 drivers/pwm/pwm-stm32-lp.c                    |  23 +-
 drivers/pwm/pwm-stm32.c                       |  46 ++--
 drivers/pwm/pwm-stmpe.c                       |  64 +++---
 drivers/pwm/pwm-sun4i.c                       |  39 ++--
 drivers/pwm/pwm-sunplus.c                     |  17 +-
 drivers/pwm/pwm-tegra.c                       |  27 ++-
 drivers/pwm/pwm-tiecap.c                      |  57 ++---
 drivers/pwm/pwm-tiehrpwm.c                    |  70 +++---
 drivers/pwm/pwm-twl-led.c                     |  62 +++---
 drivers/pwm/pwm-twl.c                         |  52 ++---
 drivers/pwm/pwm-visconti.c                    |  17 +-
 drivers/pwm/pwm-vt8500.c                      |  24 +-
 drivers/pwm/pwm-xilinx.c                      |  34 ++-
 drivers/pwm/sysfs.c                           |  45 +---
 drivers/staging/greybus/pwm.c                 |  80 ++-----
 include/linux/platform_data/x86/pwm-lpss.h    |   4 +-
 include/linux/pwm.h                           |  24 +-
 78 files changed, 1310 insertions(+), 1189 deletions(-)


base-commit: 3ccb179aa40d931eb00ef8910d7b812a95659563
prerequisite-patch-id: cc42495033fc6c784c3139f92610cc9deeb2d87e
prerequisite-patch-id: c3fb50527e1bdd0c63ffba939d24d9d347470bb6
prerequisite-patch-id: f3333980376bf2207e993d0714845f3301c86e2e
prerequisite-patch-id: b30ff565416aab449c4e14fbd6535cad52f61096
prerequisite-patch-id: bea14e240bcd525e2fd1256882e645491624f8c6
prerequisite-patch-id: cd271964ea5243e89857030e28c3e0046ae64bd9
prerequisite-patch-id: 143c8d917c67280ec8cc8465e1a8dce8f7f77618
prerequisite-patch-id: 369332bf9747e4702010d08b45eaa72496cef9ec
prerequisite-patch-id: 2df33999582eeaf1cd2a5c805b989c969577ca0c
prerequisite-patch-id: e8dad0c65b1deb6f8cd7ea2a5a08b3ab2cb2e291
prerequisite-patch-id: b540c7ef3ea7add5e54a65f480daff3018735fd3
prerequisite-patch-id: 72247967f924911ad08210638853d3d3b3d5d278
prerequisite-patch-id: 313ada72ab57438a8d54df0df9c0926bb4f69b36
prerequisite-patch-id: 318824c08f3e7d6500e3c5a47a11c5daffaea34a
prerequisite-patch-id: 921e5b577da74b4f1b666c433e182ddd3cb7e854
prerequisite-patch-id: 4e608e07dc1adf781f21274e37b72fa528b8c60a
prerequisite-patch-id: 9abd8b16e74625e2630655da7d22e75bbe0c6231
prerequisite-patch-id: 7a0daa2918f8a317333e57c1d1698078a1968720
prerequisite-patch-id: a0c8d63424241e64c3e5f9991ea04018a51fcc94
prerequisite-patch-id: 2cae8f054048b5074ed99163e476bee87cd9b7ef
prerequisite-patch-id: 8f6f3e08d426c4d349e93f5fdb3650efcd523299
prerequisite-patch-id: f7dd05d650cd2b4368ec1ce9f7db1716841a72d8
prerequisite-patch-id: e4abcc7c18f6cc49d3d4b4221cd3856189ec71d8
prerequisite-patch-id: 67e046597429677c0bfa48bb044aac39fdcc9eb2
prerequisite-patch-id: 02694b208c763f5dac10bce135cd43a7d50d979f
prerequisite-patch-id: 4317fa5ef50613649e319fff57bb507dab10909d
prerequisite-patch-id: 1483ab31d5f3f7504dda11b5f4660022152f6e88
prerequisite-patch-id: da542cefd47056ad9f5b6fd57b5218437ba7025b
prerequisite-patch-id: 9cded674bc2c8c1a899f6da498b372ae599a7e72
prerequisite-patch-id: 25c85a2b73850671bb4bc970472cfc4c1f9f59f5
prerequisite-patch-id: 07a107646a7f974ff11acb7cd08db31d6dd8f254
prerequisite-patch-id: fdf3805aa0c2f6b7bd250673755936668db6cd4a
prerequisite-patch-id: 13386aad0b7b3f163e27bcb450e9e4c8f42630d2
prerequisite-patch-id: 5b55d44ff77e37c24646bbbee4feb8adbdccfcf7
prerequisite-patch-id: 1fe585c132c1d850e573257fe30f07a7789a235f
prerequisite-patch-id: 027a0eff436112b5c76d5c50aca6eced6ace4355
prerequisite-patch-id: a4068519ff48d7e157d59d77e99b1d95fe33a987
prerequisite-patch-id: 83665e92c2a6d2b40675330bae4bcb9b4f695e48
prerequisite-patch-id: 032d7d39b0111ddc4791a1892348be5fabb1e83b

Comments

Uwe Kleine-König Sept. 26, 2023, 10:06 a.m. UTC | #1
Hello Thierry,

On Tue, Aug 08, 2023 at 07:17:50PM +0200, Uwe Kleine-König wrote:
> this series addresses the issues I reported already earlier to this
> list[1]. It is based on pwm/for-next and several patches I already sent
> out, too. Maybe some of these have to be reworked (e.g. Thierry already
> signalled not to like the patches dropping runtime error messages) but
> in the expectation that I will have to create a v2 for this series, too
> and it actually fixes a race condition, I sent the patches out for
> review anyhow. For the same reason I didn't Cc: all the individual
> maintainers.
> 
> If you want to actually test I suggest you fetch my complete history
> from
> 
> 	https://git.pengutronix.de/git/ukl/linux pwm-lifetime-tracking
> 
> . 
> 
> In the end drivers have to allocate their pwm_chip using
> pwmchip_alloc(). This is important for the memory backing the pwm_chip
> being able to have a longer life than the driver.
> 
> The motivation for this series is to prepare the pwm framework to add a
> character device for each pwm_chip for easier and faster access to PWMs
> from userspace compared to the sysfs API. For such an extension proper
> lifetime tracking is important, too, as such a device can still be open
> if a PWM disappears.

I wonder how this topic will continue. This series fixes a lifetime
issue that can result in a userspace triggered oops and it builds the
base for my efforts to create a /dev/pwmchipX for faster control of PWMs
from userspace (compared to sysfs). (Currently in the prototype stage.)

I'd like to get this in during the next merge window, please tell me
what needs to be done to make this happen.

Best regards
Uwe
Uwe Kleine-König Oct. 1, 2023, 11:10 a.m. UTC | #2
Hello again,

On Tue, Sep 26, 2023 at 12:06:25PM +0200, Uwe Kleine-König wrote:
> On Tue, Aug 08, 2023 at 07:17:50PM +0200, Uwe Kleine-König wrote:
> > this series addresses the issues I reported already earlier to this
> > list[1]. It is based on pwm/for-next and several patches I already sent
> > out, too. Maybe some of these have to be reworked (e.g. Thierry already
> > signalled not to like the patches dropping runtime error messages) but
> > in the expectation that I will have to create a v2 for this series, too
> > and it actually fixes a race condition, I sent the patches out for
> > review anyhow. For the same reason I didn't Cc: all the individual
> > maintainers.
> > 
> > If you want to actually test I suggest you fetch my complete history
> > from
> > 
> > 	https://git.pengutronix.de/git/ukl/linux pwm-lifetime-tracking
> > 
> > . 
> > 
> > In the end drivers have to allocate their pwm_chip using
> > pwmchip_alloc(). This is important for the memory backing the pwm_chip
> > being able to have a longer life than the driver.
> > 
> > The motivation for this series is to prepare the pwm framework to add a
> > character device for each pwm_chip for easier and faster access to PWMs
> > from userspace compared to the sysfs API. For such an extension proper
> > lifetime tracking is important, too, as such a device can still be open
> > if a PWM disappears.
> 
> I wonder how this topic will continue. This series fixes a lifetime
> issue that can result in a userspace triggered oops and it builds the
> base for my efforts to create a /dev/pwmchipX for faster control of PWMs
> from userspace (compared to sysfs). (Currently in the prototype stage.)
> 
> I'd like to get this in during the next merge window, please tell me
> what needs to be done to make this happen.

One problem I noticed yesterday is that this series depends on patch
"drm/ssd130x: Print the PWM's label instead of its number" that
currently waits in drm-misc-next for getting in the main line. The
series could for sure be reworked to not rely on this patch, but I'd
prefer to wait until after the next merge window instead of reworking
it.

Still, getting some feedback here in the mean time would be nice. The
questions I wonder about myself are:

 - In patch #1, devm_pwmchip_alloc() could get another parameter for the
   .ops member. This would save a line per driver like

   	chip->ops = &pwm_clk_ops;

   in return for an additional parameter that yields longer lines in the
   drivers.

 - In patch #101 instead of using &pwm_lock a per-pwmchip lock could be
   used for pwm_apply_state(). This would allow to parallelize pwm calls
   for different chips; I don't know how much this matters. Maybe the
   sensible option here is to keep it simple for now (i.e. how I
   implemented it now) until someone complains? (But see also the next
   item.)

 - A further complication is the requirement of pwm-ir-tx for faster
   pwm_apply_state() calls, see

	https://lore.kernel.org/linux-pwm/ZRb5OWvx3GxYWf9g@gofer.mess.org
   	https://lore.kernel.org/linux-pwm/1bd5241d584ceb4d6b731c4dc3203fb9686ee1d1.1696156485.git.sean@mess.org

   . This complicates the locking scheme, I didn't try to address that
   yet.

Best regards
Uwe
Thierry Reding Oct. 6, 2023, 9:20 a.m. UTC | #3
On Tue, Aug 08, 2023 at 07:17:50PM +0200, Uwe Kleine-König wrote:
> Hello,
> 
> this series addresses the issues I reported already earlier to this
> list[1]. It is based on pwm/for-next and several patches I already sent
> out, too. Maybe some of these have to be reworked (e.g. Thierry already
> signalled not to like the patches dropping runtime error messages) but
> in the expectation that I will have to create a v2 for this series, too
> and it actually fixes a race condition, I sent the patches out for
> review anyhow. For the same reason I didn't Cc: all the individual
> maintainers.
> 
> If you want to actually test I suggest you fetch my complete history
> from
> 
> 	https://git.pengutronix.de/git/ukl/linux pwm-lifetime-tracking
> 
> . 
> 
> In the end drivers have to allocate their pwm_chip using
> pwmchip_alloc(). This is important for the memory backing the pwm_chip
> being able to have a longer life than the driver.

Couldn't we achieve the same thing by just making sure that drivers
don't use any of the device-managed APIs to do this? That seems like a
slightly less intrusive way of doing things.

> The motivation for this series is to prepare the pwm framework to add a
> character device for each pwm_chip for easier and faster access to PWMs
> from userspace compared to the sysfs API. For such an extension proper
> lifetime tracking is important, too, as such a device can still be open
> if a PWM disappears.

As I mentioned before, I'd like to see at least a prototype of the
character device patches before I merge this series. There's a whole lot
of churn here and without the character device support it's hard to
justify.

I have a couple more detailed comments, but I'll leave those in response
to some of the other patches for better context.

Thierry
Thierry Reding Oct. 6, 2023, 10:15 a.m. UTC | #4
On Sun, Oct 01, 2023 at 01:10:24PM +0200, Uwe Kleine-König wrote:
> Hello again,
> 
> On Tue, Sep 26, 2023 at 12:06:25PM +0200, Uwe Kleine-König wrote:
> > On Tue, Aug 08, 2023 at 07:17:50PM +0200, Uwe Kleine-König wrote:
> > > this series addresses the issues I reported already earlier to this
> > > list[1]. It is based on pwm/for-next and several patches I already sent
> > > out, too. Maybe some of these have to be reworked (e.g. Thierry already
> > > signalled not to like the patches dropping runtime error messages) but
> > > in the expectation that I will have to create a v2 for this series, too
> > > and it actually fixes a race condition, I sent the patches out for
> > > review anyhow. For the same reason I didn't Cc: all the individual
> > > maintainers.
> > > 
> > > If you want to actually test I suggest you fetch my complete history
> > > from
> > > 
> > > 	https://git.pengutronix.de/git/ukl/linux pwm-lifetime-tracking
> > > 
> > > . 
> > > 
> > > In the end drivers have to allocate their pwm_chip using
> > > pwmchip_alloc(). This is important for the memory backing the pwm_chip
> > > being able to have a longer life than the driver.
> > > 
> > > The motivation for this series is to prepare the pwm framework to add a
> > > character device for each pwm_chip for easier and faster access to PWMs
> > > from userspace compared to the sysfs API. For such an extension proper
> > > lifetime tracking is important, too, as such a device can still be open
> > > if a PWM disappears.
> > 
> > I wonder how this topic will continue. This series fixes a lifetime
> > issue that can result in a userspace triggered oops and it builds the
> > base for my efforts to create a /dev/pwmchipX for faster control of PWMs
> > from userspace (compared to sysfs). (Currently in the prototype stage.)
> > 
> > I'd like to get this in during the next merge window, please tell me
> > what needs to be done to make this happen.
> 
> One problem I noticed yesterday is that this series depends on patch
> "drm/ssd130x: Print the PWM's label instead of its number" that
> currently waits in drm-misc-next for getting in the main line. The
> series could for sure be reworked to not rely on this patch, but I'd
> prefer to wait until after the next merge window instead of reworking
> it.
> 
> Still, getting some feedback here in the mean time would be nice. The
> questions I wonder about myself are:
> 
>  - In patch #1, devm_pwmchip_alloc() could get another parameter for the
>    .ops member. This would save a line per driver like
> 
>    	chip->ops = &pwm_clk_ops;
> 
>    in return for an additional parameter that yields longer lines in the
>    drivers.
> 
>  - In patch #101 instead of using &pwm_lock a per-pwmchip lock could be
>    used for pwm_apply_state(). This would allow to parallelize pwm calls
>    for different chips; I don't know how much this matters. Maybe the
>    sensible option here is to keep it simple for now (i.e. how I
>    implemented it now) until someone complains? (But see also the next
>    item.)
> 
>  - A further complication is the requirement of pwm-ir-tx for faster
>    pwm_apply_state() calls, see
> 
> 	https://lore.kernel.org/linux-pwm/ZRb5OWvx3GxYWf9g@gofer.mess.org
>    	https://lore.kernel.org/linux-pwm/1bd5241d584ceb4d6b731c4dc3203fb9686ee1d1.1696156485.git.sean@mess.org
> 
>    . This complicates the locking scheme, I didn't try to address that
>    yet.

Frankly, I think per-chip locking is the only way to support slow
busses. If we use the subsystem-wide lock, effectively all chips become
slow and unusable for things like pwm-ir-tx.

Perhaps we can draw some inspiration from how the IRQ infrastructure
deals with this? IRQ chips have irq_bus_lock() and irq_bus_sync_unlock()
callbacks to deal with this. We could have something similar for PWM
chips. Perhaps that's even something that could be handled in the core
by checking a "might_sleep" flag for the chip.

Thierry
Uwe Kleine-König Oct. 6, 2023, 10:41 a.m. UTC | #5
Hello Thierry,

On Fri, Oct 06, 2023 at 11:20:03AM +0200, Thierry Reding wrote:
> On Tue, Aug 08, 2023 at 07:17:50PM +0200, Uwe Kleine-König wrote:
> > this series addresses the issues I reported already earlier to this
> > list[1]. It is based on pwm/for-next and several patches I already sent
> > out, too. Maybe some of these have to be reworked (e.g. Thierry already
> > signalled not to like the patches dropping runtime error messages) but
> > in the expectation that I will have to create a v2 for this series, too
> > and it actually fixes a race condition, I sent the patches out for
> > review anyhow. For the same reason I didn't Cc: all the individual
> > maintainers.
> > 
> > If you want to actually test I suggest you fetch my complete history
> > from
> > 
> > 	https://git.pengutronix.de/git/ukl/linux pwm-lifetime-tracking
> > 
> > . 
> > 
> > In the end drivers have to allocate their pwm_chip using
> > pwmchip_alloc(). This is important for the memory backing the pwm_chip
> > being able to have a longer life than the driver.
> 
> Couldn't we achieve the same thing by just making sure that drivers
> don't use any of the device-managed APIs to do this? That seems like a
> slightly less intrusive way of doing things.

The device-managed APIs are not the problem here. If you allocate in
.probe and free in .remove there is a problem. (And that's exactly what
the device managed APIs do.)

So no, you cannot. The thing is the struct pwm_chip must stay around until
the last reference is dropped. So you need some kind of reference
counting. The canonical way to do that is using a struct device.

You can try to hide it from the low-level drivers (as gpio does) at the
cost that you have the driver allocated structure separate from the
reference counted memory under framework control. The cost is more
overhead because you have >1 memory chunk (memory fragmentation, less
cache locality) and more pointers. IMHO the cleaner way is to not hide
it and have the explicit handling needed in the drivers be not error
prone (as spi does).

I agree the switch suggested here is intrusive, but the "new way" a
driver has to look like is fine, so I'd not hesitate here.

> > The motivation for this series is to prepare the pwm framework to add a
> > character device for each pwm_chip for easier and faster access to PWMs
> > from userspace compared to the sysfs API. For such an extension proper
> > lifetime tracking is important, too, as such a device can still be open
> > if a PWM disappears.
> 
> As I mentioned before, I'd like to see at least a prototype of the
> character device patches before I merge this series. There's a whole lot
> of churn here and without the character device support it's hard to
> justify.

The character device stuff is only one reason to get the lifetime
tracking right. See that oops I can trigger today that is fixed by this
series.

> I have a couple more detailed comments, but I'll leave those in response
> to some of the other patches for better context.

Earlier today I managed to get this character support working enough to
be able to trigger pwm_apply_state calls. My test case looks
(simplified) like this:

	state.period = 50000;
	for (state.duty_cycle = 0; state.duty_cycle <= state.period; ++state.duty_cycle)
		pwm_apply_state(pwm, &state);

With a naive sysfs backend that takes approx. a minute. With an
optimized version (that only writes the duty_cycle file in the above
case) it goes down to 20s. With the character device it takes 4.7s.

Best regards
Uwe
Thierry Reding Oct. 6, 2023, 11:50 a.m. UTC | #6
On Fri, Oct 06, 2023 at 12:41:02PM +0200, Uwe Kleine-König wrote:
> Hello Thierry,
> 
> On Fri, Oct 06, 2023 at 11:20:03AM +0200, Thierry Reding wrote:
> > On Tue, Aug 08, 2023 at 07:17:50PM +0200, Uwe Kleine-König wrote:
> > > this series addresses the issues I reported already earlier to this
> > > list[1]. It is based on pwm/for-next and several patches I already sent
> > > out, too. Maybe some of these have to be reworked (e.g. Thierry already
> > > signalled not to like the patches dropping runtime error messages) but
> > > in the expectation that I will have to create a v2 for this series, too
> > > and it actually fixes a race condition, I sent the patches out for
> > > review anyhow. For the same reason I didn't Cc: all the individual
> > > maintainers.
> > > 
> > > If you want to actually test I suggest you fetch my complete history
> > > from
> > > 
> > > 	https://git.pengutronix.de/git/ukl/linux pwm-lifetime-tracking
> > > 
> > > . 
> > > 
> > > In the end drivers have to allocate their pwm_chip using
> > > pwmchip_alloc(). This is important for the memory backing the pwm_chip
> > > being able to have a longer life than the driver.
> > 
> > Couldn't we achieve the same thing by just making sure that drivers
> > don't use any of the device-managed APIs to do this? That seems like a
> > slightly less intrusive way of doing things.
> 
> The device-managed APIs are not the problem here. If you allocate in
> .probe and free in .remove there is a problem. (And that's exactly what
> the device managed APIs do.)

Heh... so you're saying that device-managed APIs are the problem here.
Yes, without device-managed APIs you still need to make sure you don't
free while the PWM devices are still in use, but at least you then have
that option.

My point was that with device-managed APIs, freeing memory at ->remove()
comes built-in. Hence why it's confusing to see that this series keeps
using device-managed APIs while claiming to address lifetime issues.

> So no, you cannot. The thing is the struct pwm_chip must stay around until
> the last reference is dropped. So you need some kind of reference
> counting. The canonical way to do that is using a struct device.
> 
> You can try to hide it from the low-level drivers (as gpio does) at the
> cost that you have the driver allocated structure separate from the
> reference counted memory under framework control. The cost is more
> overhead because you have >1 memory chunk (memory fragmentation, less
> cache locality) and more pointers. IMHO the cleaner way is to not hide

Single-chunk allocations can also lead to less cache locality, depending
on the size of your allocations. For instance if you primarily use small
driver-specific data structures, those may fit into the cache while a
combined data structure that consists of the core structure plus driver-
private data may need to be split across multiple cache lines, and you
may not end up using something like the core structure a lot of the
time.

Anyway, I'm not sure PWM is the kind of subsystem where cache locality
is something we need to be concerned about.

> it and have the explicit handling needed in the drivers be not error
> prone (as spi does).
> 
> I agree the switch suggested here is intrusive, but the "new way" a
> driver has to look like is fine, so I'd not hesitate here.
> 
> > > The motivation for this series is to prepare the pwm framework to add a
> > > character device for each pwm_chip for easier and faster access to PWMs
> > > from userspace compared to the sysfs API. For such an extension proper
> > > lifetime tracking is important, too, as such a device can still be open
> > > if a PWM disappears.
> > 
> > As I mentioned before, I'd like to see at least a prototype of the
> > character device patches before I merge this series. There's a whole lot
> > of churn here and without the character device support it's hard to
> > justify.
> 
> The character device stuff is only one reason to get the lifetime
> tracking right. See that oops I can trigger today that is fixed by this
> series.

My recollection is that you need to inject a 5 second sleep into an
apply function in order to trigger this, which is not something you
would usually do, or that someone could trigger by accident. Yes, it
might be theoretically possible to run into this, but so far nobody
has reported this to be an actual problem in practice.

Also, as you have mentioned before, other mechanisms should already
take care of tearing things down properly. If that's not happening for
some reason, that's probably what we should investigate. It'd probably
be less intrusive than 100 patches with churn in every driver.

I'm not saying we don't need this, just trying to put it into
perspective.

Thierry
Uwe Kleine-König Oct. 6, 2023, 5:05 p.m. UTC | #7
Hello Thierry,

On Fri, Oct 06, 2023 at 12:15:55PM +0200, Thierry Reding wrote:
> On Sun, Oct 01, 2023 at 01:10:24PM +0200, Uwe Kleine-König wrote:
> > On Tue, Sep 26, 2023 at 12:06:25PM +0200, Uwe Kleine-König wrote:
> > > On Tue, Aug 08, 2023 at 07:17:50PM +0200, Uwe Kleine-König wrote:
> > > > this series addresses the issues I reported already earlier to this
> > > > list[1]. It is based on pwm/for-next and several patches I already sent
> > > > out, too. Maybe some of these have to be reworked (e.g. Thierry already
> > > > signalled not to like the patches dropping runtime error messages) but
> > > > in the expectation that I will have to create a v2 for this series, too
> > > > and it actually fixes a race condition, I sent the patches out for
> > > > review anyhow. For the same reason I didn't Cc: all the individual
> > > > maintainers.
> > > > 
> > > > If you want to actually test I suggest you fetch my complete history
> > > > from
> > > > 
> > > > 	https://git.pengutronix.de/git/ukl/linux pwm-lifetime-tracking
> > > > 
> > > > . 
> > > > 
> > > > In the end drivers have to allocate their pwm_chip using
> > > > pwmchip_alloc(). This is important for the memory backing the pwm_chip
> > > > being able to have a longer life than the driver.
> > > > 
> > > > The motivation for this series is to prepare the pwm framework to add a
> > > > character device for each pwm_chip for easier and faster access to PWMs
> > > > from userspace compared to the sysfs API. For such an extension proper
> > > > lifetime tracking is important, too, as such a device can still be open
> > > > if a PWM disappears.
> > > 
> > > I wonder how this topic will continue. This series fixes a lifetime
> > > issue that can result in a userspace triggered oops and it builds the
> > > base for my efforts to create a /dev/pwmchipX for faster control of PWMs
> > > from userspace (compared to sysfs). (Currently in the prototype stage.)
> > > 
> > > I'd like to get this in during the next merge window, please tell me
> > > what needs to be done to make this happen.
> > 
> > One problem I noticed yesterday is that this series depends on patch
> > "drm/ssd130x: Print the PWM's label instead of its number" that
> > currently waits in drm-misc-next for getting in the main line. The
> > series could for sure be reworked to not rely on this patch, but I'd
> > prefer to wait until after the next merge window instead of reworking
> > it.
> > 
> > Still, getting some feedback here in the mean time would be nice. The
> > questions I wonder about myself are:
> > 
> >  - In patch #1, devm_pwmchip_alloc() could get another parameter for the
> >    .ops member. This would save a line per driver like
> > 
> >    	chip->ops = &pwm_clk_ops;
> > 
> >    in return for an additional parameter that yields longer lines in the
> >    drivers.
> > 
> >  - In patch #101 instead of using &pwm_lock a per-pwmchip lock could be
> >    used for pwm_apply_state(). This would allow to parallelize pwm calls
> >    for different chips; I don't know how much this matters. Maybe the
> >    sensible option here is to keep it simple for now (i.e. how I
> >    implemented it now) until someone complains? (But see also the next
> >    item.)
> > 
> >  - A further complication is the requirement of pwm-ir-tx for faster
> >    pwm_apply_state() calls, see
> > 
> > 	https://lore.kernel.org/linux-pwm/ZRb5OWvx3GxYWf9g@gofer.mess.org
> >    	https://lore.kernel.org/linux-pwm/1bd5241d584ceb4d6b731c4dc3203fb9686ee1d1.1696156485.git.sean@mess.org
> > 
> >    . This complicates the locking scheme, I didn't try to address that
> >    yet.
> 
> Frankly, I think per-chip locking is the only way to support slow
> busses. If we use the subsystem-wide lock, effectively all chips become
> slow and unusable for things like pwm-ir-tx.
> 
> Perhaps we can draw some inspiration from how the IRQ infrastructure
> deals with this? IRQ chips have irq_bus_lock() and irq_bus_sync_unlock()
> callbacks to deal with this. We could have something similar for PWM
> chips. Perhaps that's even something that could be handled in the core
> by checking a "might_sleep" flag for the chip.

I'll invest some time to work on that, also considering that we might
not want sleep at all for "fast" PWMs.

Best regards
Uwe
Uwe Kleine-König Oct. 6, 2023, 5:35 p.m. UTC | #8
Hello Thierry,

On Fri, Oct 06, 2023 at 01:50:57PM +0200, Thierry Reding wrote:
> On Fri, Oct 06, 2023 at 12:41:02PM +0200, Uwe Kleine-König wrote:
> > On Fri, Oct 06, 2023 at 11:20:03AM +0200, Thierry Reding wrote:
> > > On Tue, Aug 08, 2023 at 07:17:50PM +0200, Uwe Kleine-König wrote:
> > > > this series addresses the issues I reported already earlier to this
> > > > list[1]. It is based on pwm/for-next and several patches I already sent
> > > > out, too. Maybe some of these have to be reworked (e.g. Thierry already
> > > > signalled not to like the patches dropping runtime error messages) but
> > > > in the expectation that I will have to create a v2 for this series, too
> > > > and it actually fixes a race condition, I sent the patches out for
> > > > review anyhow. For the same reason I didn't Cc: all the individual
> > > > maintainers.
> > > > 
> > > > If you want to actually test I suggest you fetch my complete history
> > > > from
> > > > 
> > > > 	https://git.pengutronix.de/git/ukl/linux pwm-lifetime-tracking
> > > > 
> > > > . 
> > > > 
> > > > In the end drivers have to allocate their pwm_chip using
> > > > pwmchip_alloc(). This is important for the memory backing the pwm_chip
> > > > being able to have a longer life than the driver.
> > > 
> > > Couldn't we achieve the same thing by just making sure that drivers
> > > don't use any of the device-managed APIs to do this? That seems like a
> > > slightly less intrusive way of doing things.
> > 
> > The device-managed APIs are not the problem here. If you allocate in
> > .probe and free in .remove there is a problem. (And that's exactly what
> > the device managed APIs do.)
> 
> Heh... so you're saying that device-managed APIs are the problem here.

No, I'm just saying that replacing devm_kzalloc by kzalloc in .probe and
free in .remove (and .probe's error path) doesn't help, because that's
what devm_kzalloc does under the cover.

> Yes, without device-managed APIs you still need to make sure you don't
> free while the PWM devices are still in use, but at least you then have
> that option.

The big downside I see then is that each driver must cope to get the
free at the right place. Using devm_pwmchip_alloc() puts that complexity
into a single place in the core instead.

> My point was that with device-managed APIs, freeing memory at ->remove()
> comes built-in. Hence why it's confusing to see that this series keeps
> using device-managed APIs while claiming to address lifetime issues.

This is only part of the preparations. In the end there is no
devm_kzalloc() any more. (And the cleanup handler of
devm_pwmchip_alloc() calls put_device() which only triggers kfree() once
all references are gone.)
 
> > So no, you cannot. The thing is the struct pwm_chip must stay around until
> > the last reference is dropped. So you need some kind of reference
> > counting. The canonical way to do that is using a struct device.
> > 
> > You can try to hide it from the low-level drivers (as gpio does) at the
> > cost that you have the driver allocated structure separate from the
> > reference counted memory under framework control. The cost is more
> > overhead because you have >1 memory chunk (memory fragmentation, less
> > cache locality) and more pointers. IMHO the cleaner way is to not hide
> 
> Single-chunk allocations can also lead to less cache locality, depending
> on the size of your allocations. For instance if you primarily use small
> driver-specific data structures, those may fit into the cache while a
> combined data structure that consists of the core structure plus driver-
> private data may need to be split across multiple cache lines, and you
> may not end up using something like the core structure a lot of the
> time.

I think this is wrong. Two memory chunks of size A and B are never
better than a single memory chunk of size A+B for caching. Those small
driver-specific data structures all live in the B part. For cache
locality of this driver struct it doesn't matter if A is directly in
front of that or somewhere else. But with having these in a single chunk
you might benefit from better caching when accessing both A and B, and
simpler page handling and less memory management overhead.

> Anyway, I'm not sure PWM is the kind of subsystem where cache locality
> is something we need to be concerned about.

pwm-ir-tx is concerned about timing, and my customer controlling a motor
wants little overhead, too. I don't have hard numbers, but I tend to
invest that effort.

> > it and have the explicit handling needed in the drivers be not error
> > prone (as spi does).
> > 
> > I agree the switch suggested here is intrusive, but the "new way" a
> > driver has to look like is fine, so I'd not hesitate here.
> > 
> > > > The motivation for this series is to prepare the pwm framework to add a
> > > > character device for each pwm_chip for easier and faster access to PWMs
> > > > from userspace compared to the sysfs API. For such an extension proper
> > > > lifetime tracking is important, too, as such a device can still be open
> > > > if a PWM disappears.
> > > 
> > > As I mentioned before, I'd like to see at least a prototype of the
> > > character device patches before I merge this series. There's a whole lot
> > > of churn here and without the character device support it's hard to
> > > justify.
> > 
> > The character device stuff is only one reason to get the lifetime
> > tracking right. See that oops I can trigger today that is fixed by this
> > series.
> 
> My recollection is that you need to inject a 5 second sleep into an
> apply function in order to trigger this, which is not something you
> would usually do, or that someone could trigger by accident.
> 
> Yes, it might be theoretically possible to run into this, but so far
> nobody has reported this to be an actual problem in practice.

It is theoretically possible, and in my book that's a good enough reason
to fix it. A use-after-free is relevant for the security of the whole
system, so nobody telling us to have hit that problem isn't an excuse.

> Also, as you have mentioned before, other mechanisms should already
> take care of tearing things down properly. If that's not happening for
> some reason, that's probably what we should investigate. It'd probably
> be less intrusive than 100 patches with churn in every driver.

Let's do some work sharing: I continue with the lifetime stuff (that we
need for the character device stuff anyway) and the character device
code and you check why device links don't work as expected? I cannot
cope for every potential bug I notice, at least not always on the front
of my todo list :-)

Best regards
Uwe