Driver / Device · Linux v6.6 · source + diagram note

runtime PM

pm_runtime_get/put, autosuspend.

전체 흐름

Runtime PM은 시스템 전체 suspend와 별개로 개별 device의 사용 횟수와 PM core 상태를 관리합니다. pm_runtime_get()·pm_runtime_put()의 반환은 비동기 요청의 결과이며 PM core의 상태 전환 완료와 구분해야 합니다.

그림 1. get/put 요청과 나중의 상태 완료를 분리해서 읽기
GET
사용 시작
pm_runtime_get()usage_count 증가; RPM_ASYNC resume 요청
요청 이후이미 active일 수도 있고, resume 작업이 대기·진행 중일 수도 있음
완료 확인이미 RPM_ACTIVE인지, PM core의 resume 전환이 성공했는지 확인; callback이 실행되면 그 결과도 포함
PUT
사용 종료
pm_runtime_put()usage_count 감소; 0이면 async idle 검사 요청
조건부 idlechild, callback, autosuspend delay, 새 get 등에 따라 suspend 생략·연기 가능
완료 확인PM core가 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

원본 코드: include/linux/pm_runtime.h:406-409 · v6.6 · 로컬 원문
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

원본 코드: include/linux/pm_runtime.h:458-461 · v6.6 · 로컬 원문
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가 사용을 마친 후의 별도 시점입니다.

wrapper가 하는 일과 반환 시 보장하지 않는 것
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가 보는 상태입니다. 왼쪽에서 오른쪽으로 실행되는 필드 목록이 아닙니다.

struct device.power에서 분리해 읽을 필드
필드의미주의
power.usage_countdevice에 남은 runtime PM 사용 참조0이어야 idle/suspend를 검토할 수 있지만 0만으로 suspend 확정은 아님
power.runtime_statusRPM_ACTIVE / RPM_SUSPENDED 및 처리 중 상태PM core의 판단; counter와 동일한 값이 아니며 물리 전력 상태와도 꼭 일치하지 않음
power.request_pending / work비동기 요청의 보류와 PM workqueue 작업요청 접수와 PM core 상태 전환 완료는 다른 시점
power.child_count / ignore_childrenactive child 제약usage_count가 0이어도 suspend가 막힐 수 있음
power.last_busy / autosuspend_delay비활동 시작 시각과 지연 정책일반 pm_runtime_put()만으로 last_busy 갱신을 가정하지 않음
power.runtime_errorcallback 결과를 저장; 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 실행을 건너뛸 수 있습니다.

그림 2. 안정 상태와 PM core의 전환 중 상태
RPM_SUSPENDED ↗ RPM_RESUMINGresume 전환 경로에 들어간 경우; no_callbacks면 건너뛸 수 있음
RPM_ACTIVE ↘ RPM_SUSPENDINGsuspend 전환 경로에 들어간 경우; no_callbacks면 건너뛸 수 있음
resume 성공 → RPM_ACTIVE실패·대기·이미 active인 경우는 별도 분기
suspend 성공 → RPM_SUSPENDED-EBUSY/-EAGAIN 등으로 유지·재시도될 수 있음

두 열은 병렬로 선택 가능한 방향을 그린 것이며, 위에서 아래까지 모든 칸을 순서대로 지나는 파이프라인이 아닙니다.

사용 참조와 독립적으로 읽을 PM core 상태
상태뜻주의
RPM_SUSPENDED안정 상태; PM core가 suspended로 판단실제 하드웨어 상태를 그대로 읽은 센서값이 아님
RPM_RESUMINGPM core의 runtime-resume 처리 중; 선택된 callback이 있으면 실행비동기 get 반환과 완료를 구분
RPM_ACTIVEPM core가 판단한 active 안정 상태사용 횟수가 0일 수도 있음
RPM_SUSPENDINGPM 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와 오류 처리를 사용합니다.

idle 제약

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_statusPM 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를 직접 갱신하는가?