전체 흐름
Runtime PM은 시스템 전체 suspend와 별개로 개별 device의 사용 횟수와 PM core 상태를 관리합니다. pm_runtime_get()·pm_runtime_put()의 반환은 비동기 요청의 결과이며 PM core의 상태 전환 완료와 구분해야 합니다.
사용 시작
pm_runtime_get()usage_count 증가; RPM_ASYNC resume 요청RPM_ACTIVE인지, PM core의 resume 전환이 성공했는지 확인; callback이 실행되면 그 결과도 포함사용 종료
pm_runtime_put()usage_count 감소; 0이면 async idle 검사 요청RPM_SUSPENDED로 기록했는지 확인; callback이 실행되면 그 결과도 반영세 칸은 함수 호출의 직접 체인이 아니라 요청 → 조건부 대기·처리 → 성공 시 관찰 상태의 구분입니다. 비동기 get 반환만으로 즉시 register I/O를 시작하지 않습니다.
고정 include/linux/pm_runtime.h SHA-256 0c01daf2dc13cfd2cb6d7e293fe55c734a835af6aed445f435b0b3b80555aab4. get wrapper: 406–409 · put wrapper: 458–461. Linux runtime PM 문서.
소스 코드 위치
먼저 확인할 Linux v6.6 소스 파일
Linux v6.6: drivers/base/power/runtime.c
Linux v6.6: drivers/base/power/main.c
Linux v6.6: include/linux/pm_runtime.h
읽는 순서: pm_runtime_get/put의 정확한 wrapper 계약은 include/linux/pm_runtime.h에서, 비동기 요청 처리와 callback 선택은 drivers/base/power/runtime.c에서 봅니다. drivers/base/power/main.c의 시스템 전원 전환과 혼동하지 않습니다.
대표 코드
pm_runtime_get
static inline int pm_runtime_get(struct device *dev)
{
return __pm_runtime_resume(dev, RPM_GET_PUT | RPM_ASYNC);
}
pm_runtime_get()은 __pm_runtime_resume()에 RPM_GET_PUT와 RPM_ASYNC를 넘긴다. usage count 증가와 비동기 resume 요청이므로 반환만으로 장치가 이미 사용 가능한 상태라고 단정하지 않는다. 동기 resume가 필요하면 그 계약에 맞는 별도 API와 오류 처리가 필요하다.
pm_runtime_put
static inline int pm_runtime_put(struct device *dev)
{
return __pm_runtime_idle(dev, RPM_GET_PUT | RPM_ASYNC);
}
pm_runtime_put()은 __pm_runtime_idle()에 RPM_GET_PUT와 RPM_ASYNC를 넘겨 사용 참조를 내리고 비동기 idle 처리를 요청한다. get/put 호출은 참조 균형을 맞춰야 하며, 이 wrapper가 반환한 시점과 실제 suspend 완료는 다르다.
함수별 분석
API 이름에서 동기·비동기 계약과 사용 참조 처리 방식을 구분합니다. get 뒤 put은 caller가 사용을 마친 후의 별도 시점입니다.
| API | 요청·카운트 | 읽을 때 주의 |
|---|---|---|
pm_runtime_get() | usage_count 증가 + async resume 요청 | 반환만으로 ACTIVE 보장 안 됨 |
pm_runtime_resume_and_get() | 동기 resume 성공 시 사용 참조 유지; 오류면 참조 원복 | 즉시 사용해야 하는 경로의 오류 처리에 적합 |
pm_runtime_get_sync() | 동기 resume를 시도하고 사용 참조 증가 | 오류 때도 참조가 증가한 채 남을 수 있어 별도 균형 처리 필요 |
pm_runtime_put() | 참조 감소; 결과가 0이면 async idle 검사 요청 | put_autosuspend와 같지 않으며 즉시 SUSPENDED도 아님 |
pm_runtime_put_autosuspend() | RPM_AUTO를 사용한 별도 API | 두 버전의 last_busy 처리 차이 확인 |
v6.6 pm_runtime_put_autosuspend()는 RPM_AUTO를 전달하지만 이 wrapper 자체는 last_busy를 갱신하지 않습니다. 비활동 기간의 시작을 갱신하려면 pm_runtime_mark_last_busy() 호출 위치를 함께 확인해야 합니다.
고정 include/linux/pm_runtime.h SHA-256 0c01daf2dc13cfd2cb6d7e293fe55c734a835af6aed445f435b0b3b80555aab4. 동기 get: 425–449 · autosuspend: 470–474. Linux runtime PM 문서.
구조체와 필드
usage_count는 사용 참조, runtime_status는 PM core가 보는 상태입니다. 왼쪽에서 오른쪽으로 실행되는 필드 목록이 아닙니다.
| 필드 | 의미 | 주의 |
|---|---|---|
power.usage_count | device에 남은 runtime PM 사용 참조 | 0이어야 idle/suspend를 검토할 수 있지만 0만으로 suspend 확정은 아님 |
power.runtime_status | RPM_ACTIVE / RPM_SUSPENDED 및 처리 중 상태 | PM core의 판단; counter와 동일한 값이 아니며 물리 전력 상태와도 꼭 일치하지 않음 |
power.request_pending / work | 비동기 요청의 보류와 PM workqueue 작업 | 요청 접수와 PM core 상태 전환 완료는 다른 시점 |
power.child_count / ignore_children | active child 제약 | usage_count가 0이어도 suspend가 막힐 수 있음 |
power.last_busy / autosuspend_delay | 비활동 시작 시각과 지연 정책 | 일반 pm_runtime_put()만으로 last_busy 갱신을 가정하지 않음 |
power.runtime_error | callback 결과를 저장; suspend의 일시 오류는 실패 경로에서 해제 | 정상적인 요청 처리와 복구 경로를 나눠 봄 |
필드와 callback 제약: Linux runtime PM device fields · callback 계약.
rpm_callback()는 callback 결과를 runtime_error에 저장하고, -EACCES는 반환할 때 -EIO로 바꾼다. rpm_suspend() 실패 경로는 -EAGAIN/-EBUSY이면 저장된 오류를 0으로 지우며, autosuspend 재시도 조건을 따로 확인한다. callback 결과 처리 · suspend 실패 처리
실행 단계와 상태 변화
상태 이름은 API 호출 이름이 아닙니다. PM core는 전환 처리 중의 중간 상태를 기록할 수 있고, 성공하면 안정 상태를 기록합니다. no_callbacks 경로는 중간 상태와 callback 실행을 건너뛸 수 있습니다.
no_callbacks면 건너뛸 수 있음no_callbacks면 건너뛸 수 있음두 열은 병렬로 선택 가능한 방향을 그린 것이며, 위에서 아래까지 모든 칸을 순서대로 지나는 파이프라인이 아닙니다.
| 상태 | 뜻 | 주의 |
|---|---|---|
RPM_SUSPENDED | 안정 상태; PM core가 suspended로 판단 | 실제 하드웨어 상태를 그대로 읽은 센서값이 아님 |
RPM_RESUMING | PM core의 runtime-resume 처리 중; 선택된 callback이 있으면 실행 | 비동기 get 반환과 완료를 구분 |
RPM_ACTIVE | PM core가 판단한 active 안정 상태 | 사용 횟수가 0일 수도 있음 |
RPM_SUSPENDING | PM core의 runtime-suspend 처리 중; 선택된 callback이 있으면 실행 | 비동기 put 반환과 완료를 구분 |
상태 전환과 callback 오류 계약: Linux runtime PM 문서 §2 · §3.
불변 조건과 실패 사례
성공한 사용 획득은 알맞은 put과 짝을 맞춥니다. pm_runtime_get_sync()는 오류 때도 증가분을 남길 수 있으므로 오류 분기를 확인합니다.
pm_runtime_get()가 0을 반환해도 PM core의 resume 전환 완료나 register 접근 가능을 뜻하지 않습니다. 동기 보장이 필요한 경로는 동기 API와 오류 처리를 사용합니다.
usage_count가 0이 되어도 active child, driver idle 판단, autosuspend delay 또는 새 요청으로 suspend가 미뤄질 수 있습니다.
runtime PM 상태와 system suspend/resume는 별도 계약입니다. IRQ wakeup이나 PM domain callback의 조건을 함께 대조합니다.
계측과 검증
요청 시각과 PM core 상태 전환 완료 시각을 구분해 같은 device를 따라갑니다. usage_count는 드라이버의 get/put 지점 또는 적절한 계측으로, runtime_status는 PM core 관점으로 확인합니다.
| 관찰 지점 | 볼 것 | 한계 |
|---|---|---|
power/runtime_status | PM core가 보는 active/suspended/진행 상태 | async 요청 직후의 한 순간을 완료로 읽지 않음 |
power/control | 사용자 공간의 runtime PM 허용 정책 | driver 내부 usage_count 자체가 아님 |
power/autosuspend_delay_ms | 구성된 지연 시간 | 지연값만으로 실제 suspend 실행 여부를 알 수 없음 |
| runtime PM tracepoint / 선택된 callback 로그 | 요청·상태 전환 및 callback이 있다면 시작·종료·반환값의 시간차 | 설정에 따라 event 제공·이름이 달라질 수 있으므로 tracefs에서 확인 |
추가 확인 사항
- caller는 비동기 resume 요청만 필요한가, 실제 register I/O 전에 동기 ACTIVE 보장이 필요한가?
- 오류 분기에서도 획득한 usage_count가 정확히 한 번 내려가는가?
- put 뒤 usage_count가 0이어도 active child·idle callback·autosuspend delay 중 어느 조건이 suspend를 막는가?
- 이 버전의
pm_runtime_put_autosuspend()가last_busy를 직접 갱신하는가?