Skip to content

Zephyr PM APIs confusion #75963

@fabiobaltieri

Description

@fabiobaltieri

Introduction

Hi, I've been working with few chips using PM and PM_DEVICE recently and found some lack of clarity in the PM APIs and how/when they should be used.

Problem description

There's three main PM config options that control the system behavior, let's see if I got them right:

  • PM: enables CPU power states, basically a callback that says "hey CPU, I won't need you for a while, go to sleep"
  • PM_DEVICE: controls whether the device suspend/resume APIs are available and especially whether those xxx_pm_action driver callback are built or not
  • PM_DEVICE_RUNTIME: adds reference counters on the stuff above, with a different API, if the device enables the runtime features either with pm_device_runtime_enable or zephyr,pm-device-runtime-auto
  • PM_DEVICE_SYSTEM_MANAGED: enables the stuff in subsys/pm/device_system_managed.c, which basically means that now the system calls suspend and resume on all devices every time the CPU goes to sleep for too long, unless they are busy or flagged for pm runtime operation

So if you are running on a system that is using PM and PM_DEVICE, the default setting is PM_DEVICE_SYSTEM_MANAGED=y which means that all of your devices implementing PM are going to be suspended and resume continuously as the CPU goes to sleep and resume. I guess this would be fine if the PM device API were meant to be used for that reason, like preparing drivers to wake up the CPU early if needed, but the problem is that this is not how they are used all the time.

If one does a quick grep for PM_DEVICE_DT_INST_DEFINE in drivers/ there's a lot of usage of this for devices external of the CPU, displays, flash memories, GNSS, LED controllers, sensors, let's ignore all the input ones that I did while (clearly) not understanding what these were for. All of these clearly don't want to be suspended every time the CPU sleeps for a few milliseconds, but that's what happens, it's the same API. You may argue it's API misuse, but then if the device callback were meant to be hard bound to the CPU going in and out of sleep, why would PM_DEVICE be decoupled from PM?

Now one can disable PM_DEVICE_SYSTEM_MANAGED, but now some of the drivers that do want that callback when the CPU suspends are not going to get it anymore, and there's no way out.

So one can use PM_DEVICE_RUNTIME instead and ensure to all the devices that are NOT bound to the CPU have runtime PM enabled and are controlled by the application, but then this disables PM_DEVICE_SYSTEM_MANAGED by default... why?!

Now, PM_DEVICE_RUNTIME, how's that supposed to be used? There's load of drivers calling pm_device_runtime_enable on themselves so that they use the runtime API automatically once enabled, but then that means that once a driver gets that call introduced it changes from being active by default to suspended by default and MUST be enabled manually by the application, which inevitably causes a regression downstream. So maybe it should not be used in the driver? And we should rely on zephyr,pm-device-runtime-auto or the application calling pm_device_runtime_enable on the device? It seems to make more sense, but then how does one handle pm_device_init_suspended (which is often paired with self pm_device_runtime_enable).

Proposed change

These APIs and use cases needs to be clear as a start, right now it seems like there's a bit of a mess in the code base, the PM callback are used with different scope.

The whole PM_DEVICE_SYSTEM_MANAGED story seems to be the immediate problem, at least it is to me right now. I think that this should not be a single option that enables/disables cpu-device hooks, maybe it should be a PM_DEVICE_FLAG_ bit? PM_DEVICE_FLAG_SYSTEM_MANAGED or something?

Looking for initial feedback on this, trying to confirm if there's something I'm missing.

Metadata

Metadata

Assignees

Labels

RFCRequest For Comments: want input from the communityarea: Power Management

Type

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions