Linux v6.6 · 개념과 코드 읽기

Runtime PM: 장치를 쓰는 동안 잠들지 않게 하는 방법

이 코드는 어떤 문제를 푸나요?

시스템 전체가 켜져 있어도 사용하지 않는 장치는 전력을 줄이려고 정지할 수 있습니다. Runtime PM은 장치별 사용량과 상태를 관리하면서 필요한 때 드라이버의 재개 동작을 실행합니다. __pm_runtime_resume 전체는 사용 계수를 선택적으로 올리고 상태 잠금을 잡아 내부 재개 절차에 넘기는 입구입니다. 실제 하드웨어 전원 복구는 rpm_resume과 장치별 콜백에서 이어집니다.

읽을 범위: v6.6 · drivers/base/power/runtime.c · __pm_runtime_resume 1158–1174행입니다. 아래에 이 범위의 원문과 각 줄의 설명을 실었습니다. 주제 전체의 흐름과 다른 경로는 기존 분석에서 함께 읽으실 수 있습니다.

먼저 알아둘 개념

usage_count

장치 사용 요청의 균형을 추적하는 계수입니다. 이를 올렸다면 대응하는 put이 필요합니다. CPU 사용률이나 현재 전력량을 나타내는 값이 아닙니다.

runtime 상태

ACTIVE·SUSPENDED 등 장치 전원관리 상태를 나타냅니다. 사용 계수와 상태는 관련 있지만 같은 변수나 같은 사건은 아닙니다.

동기·비동기 재개

동기 재개는 호출 경로에서 기다릴 수 있고 비동기 재개는 작업을 요청하고 돌아올 수 있습니다. 비동기 요청 후 즉시 하드웨어 접근이 가능하다고 가정해서는 안 됩니다.

autosuspend

마지막 사용 후 일정 시간 등을 고려해 자동 정지를 요청하는 정책입니다. put을 호출한 순간 모든 장치가 즉시 물리적으로 꺼진다는 뜻은 아닙니다.

처음 읽을 때

장치를 사용하겠다고 계수를 올리는 일과 장치가 실제 ACTIVE가 되는 일을 분리해 보십시오. 특히 오류가 나면 API가 계수를 자동 복구하는지 호출자가 정리해야 하는지 확인해야 합니다.

더 깊이 살펴볼 때

RPM_GET_PUT가 있는 경우 재개 시도 이전에 계수를 증가시킵니다. __pm_runtime_resume 자체에는 실패 시 계수를 되돌리는 코드가 없으므로 get_sync와 resume_and_get 등 상위 API의 오류 처리 차이를 정확히 읽어야 합니다.

그림으로 보는 변화

Runtime PM: 장치를 쓰는 동안 잠들지 않게 하는 방법의 단계별 개념 그림
각 단계에 화살표 의미와 생략 범위를 표시했습니다. 주소·숫자 예제는 실제 장치 값을 뜻하지 않습니다.
1단계 설명

1단계 고정

GIF 원본 열기

1. 사용 요청을 반영합니다

플래그가 요구하면 장치 usage_count를 증가시킵니다.

화살표는 소프트웨어 사용량 계수의 변화이며 전원 공급 전압 변화가 아닙니다.

2. 상태를 보호하며 재개합니다

장치의 전원관리 잠금을 잡고 rpm_resume에 재개 방식을 넘깁니다.

화살표는 상태 전이 요청입니다. 비동기면 완료는 뒤에 올 수 있습니다.

3. 결과에 맞춰 접근합니다

호출자는 반환 결과와 사용한 API의 규칙을 확인한 뒤 장치를 사용하고 대응하는 put을 수행합니다.

화살표는 사용 수명입니다. 실패 정리는 상위 API의 동작에 따라 달라집니다.

__pm_runtime_resume를 한 줄씩 읽기

줄 번호는 v6.6 원문 기준입니다. 주석·빈 줄을 포함한 함수 전체를 먼저 보고, 그 아래에서 각 줄을 설명합니다.

int __pm_runtime_resume(struct device *dev, int rpmflags)
{
	unsigned long flags;
	int retval;

	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe &&
			dev->power.runtime_status != RPM_ACTIVE);

	if (rpmflags & RPM_GET_PUT)
		atomic_inc(&dev->power.usage_count);

	spin_lock_irqsave(&dev->power.lock, flags);
	retval = rpm_resume(dev, rpmflags);
	spin_unlock_irqrestore(&dev->power.lock, flags);

	return retval;
}
int __pm_runtime_resume(struct device *dev, int rpmflags)

재개할 장치와 동기·비동기, 사용 계수 변경 여부 등의 rpmflags를 받습니다.

	unsigned long flags;

잠금 전 인터럽트 상태를 저장할 변수입니다.

	int retval;

내부 재개 함수의 결과를 보관합니다.

	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe &&

비동기가 아니며 IRQ 안전 장치도 아닌 경우 잠들 수 있는 호출인지 검사할 조건을 구성합니다.

			dev->power.runtime_status != RPM_ACTIVE);

이미 ACTIVE가 아닌 경우에만 might_sleep_if 진단을 적용합니다. 이 매크로 자체가 장치를 재개하거나 일부러 잠드는 것은 아닙니다.

	if (rpmflags & RPM_GET_PUT)

이번 API가 사용 계수도 함께 증가시키도록 요구했는지 확인합니다.

		atomic_inc(&dev->power.usage_count);

동시 사용자와 충돌하지 않도록 usage_count를 원자적으로 증가시킵니다.

	spin_lock_irqsave(&dev->power.lock, flags);

인터럽트 상태를 보존하고 장치 전원관리 상태를 보호하는 스핀락을 잡습니다.

	retval = rpm_resume(dev, rpmflags);

내부 상태 기계에 장치와 플래그를 넘겨 실제 재개 처리 또는 예약을 수행합니다.

	spin_unlock_irqrestore(&dev->power.lock, flags);

상태 잠금을 풀고 진입 전 인터럽트 상태로 돌립니다.

	return retval;

재개 처리 결과를 반환합니다. 사용 계수 증가를 이 함수 안에서 자동 취소하지 않는다는 점을 확인하십시오.

함께 생각해 볼 질문

usage_count를 올리면 장치가 즉시 켜지나요?

계수와 실제 재개는 별도입니다. 이후 rpm_resume의 결과와 동기·비동기 방식도 확인해야 합니다.

재개가 실패하면 이 함수가 계수를 자동으로 내리나요?

이 함수 본문에는 그런 코드가 없습니다. 사용한 상위 API가 되돌리는지 호출자가 해야 하는지 확인해야 합니다.

Runtime PM은 시스템 suspend와 같은가요?

시스템 전체 절전과 별도로 개별 장치의 유휴 상태를 관리하는 기능입니다.

출처와 읽은 범위

Linux stable v6.6 · drivers/base/power/runtime.c

해당 버전 원본 파일 · 기존 코드 분석 · 설명 원고

맨 위로 ↑