[Linux:Kernel] Linux CPUFreq User guide

이 문서의 저작권은 GPL을 따릅니다.(This document is released under the GPL license.)

            리눅스(TM) 커널 안의 CPU 주파수와 전압 조정 코드
                         L i n u x    C P U F r e q
                             U S E R   G U I D E
                    Dominik Brodowski  <linux@brodo.de>
                번역 : 양정석 <dasomoli@gmailREMOVETHIS.com>
   Clock scaling allows you to change the clock speed of the CPUs on the
    fly. This is a nice method to save battery power, because the lower
            the clock speed, the less power the CPU consumes.
차례:
—–
1. 지원되는 아키텍처와 프로세서들
1.1 ARM
1.2 x86
1.3 sparc64
1.4 ppc
1.5 SuperH
1.6 Blackfin
2. “정책” / “가버너”?
2.1 정책
2.2 가버너
3. CPU cpufreq 정책과(또는) 속도를 어떻게 바꾸는지
3.1 선호되는 인터페이스: sysfs
1. 지원되는 아키텍처와 프로세서들
=================================
1.1 ARM
——-
다음의 ARM 프로세서들이 cpufreq 에 의해 지원됩니다:
ARM Integrator
ARM-SA1100
ARM-SA1110
Intel PXA
1.2 x86
——-
다음의 x86 아키텍처의 프로세서들이 cpufreq 에 의해 지원됩니다:
AMD Elan – SC400, SC410
AMD mobile K6-2+
AMD mobile K6-3+
AMD mobile Duron
AMD mobile Athlon
AMD Opteron
AMD Athlon 64
Cyrix Media GXm
Intel mobile PIII 와 확실한 칩셋 상의 Intel mobile PIII-M
Intel Pentium 4, Intel Xeon
Intel Pentium M (Centrino)
National Semiconductors Geode GX
Transmeta Crusoe
Transmeta Efficeon
VIA Cyrix 3 / C3
ACPI 2.0 호환 시스템 상의 다양한 프로세서들 [*]
[*] “ACPI 프로세서 성능 상태” 들이 ACPI<->BIOS 인터페이스로 이용
가능한 경우만.
1.3 sparc64
———–
다음의 sparc64 아키텍처의 프로세서들이 cpufreq 에 의해 지원됩니다:
UltraSPARC-III
1.4 ppc
——-
여러 “PowerBook” 과 “iBook2” 노트북들이 지원됩니다.
1.5 SuperH
———-
클럭 프레임워크를 통해 속도 반올림을 지원하는 모든 SuperH 프로세서가 
cpufreq 에 의해 지원됩니다.
1.6 Blackfin
————
다음의 Blackfin 프로세서들이 cpufreq 에 의해 지원됩니다:
BF522, BF523, BF524, BF525, BF526, BF527, Rev 0.1 또는 그 이상
BF531, BF532, BF533, Rev 0.3 또는 그 이상
BF534, BF536, BF537, Rev 0.2 또는 그 이상
BF561, Rev 0.3 또는 그 이상
BF542, BF544, BF547, BF548, BF549, Rev 0.1 또는 그 이상
2. “정책” / “가버너” ?
======================
몇몇 CPU 주파수 조정-가능 프로세서는 다양한 주파수들과 동작 전압 사이를
“실행 중에” 어떤 커널이나 사용자 간섭없이 변환합니다. 이것은 사용자가
필요로 하는 것을 해주기에 충분히 높은, 그러나 전력을 절약하기에 충분한
주파수로의 매우 빠른 변환을 보장합니다.
2.1 정책
——–
이들 시스템 상에서, 여러분이 할 수 있는 모든 것은 여러분이 더 공격적인
전력-절약을 원하는만큼 또는 더 즉각적인 처리 능력을 원하는지에 맞춰
높고 낮은 주파수 제한 사항을 선택하는 것입니다.
2.2 가버너
———-
모든 다른 cpufreq 구현 상에서, 이들 경계는 여전이 셋팅될 필요가 있습니다.
그럼 “가버너”가 반드시 선택되어야 합니다. 앞서 언급한 “가버너”는 프로세서가
어떤 속도를 경계안에서 사용할 것인지를 결정합니다. 이런 “가버너”는
“사용자공간” 가버너입니다. 이것은 사용자 – 또는 아직 구현되지 않은
사용자공간 프로그램이 그 프로세서가 어떤 지정된 속도로 실행할지를
결정하도록 할 수 있습니다.
3. CPU cpufreq 정책과(또는) 속도를 어떻게 바꾸는지
==================================================
3.1 선호되는 인터페이스: sysfs
——————————
선호되는 인터페이스는 sysfs 파일시스템 안에 위치합니다. 여러분이
/sys에 그것을 마운트하였다면, cpufreq 인터페이스는 cpu-device 디렉토리
안의 그 하위 디렉토리 “cpufreq” 에 위치합니다
(예를 들면, 첫번째 CPU를 위해 /sys/devices/system/cpu/cpu0/cpufreq).
cpuinfo_min_freq :              이 파일은 그 프로세서가 실행할 수 있는 최하
                                동작 주파수(hKz)를 보여줍니다.
cpuinfo_max_freq :              이 파일은 그 프로세서가 실행할 수 있는 최고
                                동작 주파수(kHZ)를 보여줍니다.
cpuinfo_transition_latency      이 CPU 상에서 두 주파수 사이에 변환되는데
                                걸리는 나노초 시간. 알려져 있지 않거나,
                                ondemand 가버너로 그 드라이버가 동작하지
                                않는 높은 값으로 알려지면, -1
                                (CPUFREQ_ETERNAL) 이 반환될 것입니다.
                                이 정보를 사용하는 것은 커널 가버너나
                                사용자공간 대몬을 위한 주파수의 폴링을
                                선택하는데 유용합니다. 성능 저하 상 너무
                                잦은 결과치 산출로 주파수를 변환하지 않도록
                                하세요.
                                
scaling_driver :                이 파일은 이 CPU 상의 주파수를 셋팅하는데
                                무슨 cpufreq 드라이버가 사용되는지 보여줍니다.
scaling_available_governors :   이 파일은 이 커널 안의 사용가능한 CPUfreq
                                가버너들을 보여줍니다. 여러분은 현재 활성화된
                                가버너를 볼 수 있습니다.
scaling_governor,               그리고 다른 가버너의 이름을 “echo함”으로써,
                                여러분은 이를 바꿀 수 있습니다. 어떤 가버너는
                                로딩되지 않을 것임을 알아두세요 – 그들은 오직
                                어떤 지정된 아키텍처나 프로세스들 상에서만
                                동작합니다.
cpuinfo_cur_freq :              하드웨어로부터 얻은 그 CPU의 현재 주파수(kHZ).
                                이 것은 CPU가 실제로 실행되는 주파수입니다.
scaling_available_frequencies : 사용가능한 주파수의 목록(KHz)
scaling_min_freq 와
scaling_max_freq                현재의 “정책 제한 사항”을 보여줍니다(kHz).
                                새로운 값들을 이 파일에 echo함으로써,
                                여러분은 이들 제한 사항을 바꿀 수 있습니다.
                                알림: 여러분이 필요로 하는 정책을 셋팅할 때
                                먼저 scaling_max_freq를 셋팅하고, 그 다음
                                scaling_min_freq를 셋팅하세요.
affected_cpus :                 주파수의 소프트웨어 조정이 요구되는 CPU들의 목록
related_cpus :                  소프트웨어든 하드웨어든 일련의 주파수 조정이
                                필요한 CPU들의 목록
scaling_driver :                cpufreq를 위한 하드웨어 드라이버.
scaling_cur_freq :              가버너와 cpufreq 코어에 의해 결정된 그 CPU의
                                현재 주파수(kHz). 이것은 커널이 그 CPU가
                                실행한다고 생각하는 주파수입니다.
bios_limit :                    BIOS가 OS에게 CPU를 더 낮은 주파수로 제한하라고
                                이야기한다면, 사용자는 이 파일로부터 최고
                                사용가능 주파수를 읽을 수 있습니다. 이것은
                                일반적으로 (종종 의도되지 않은) BIOS 셋팅,
                                서비스 프로세서나 다른 BIOS/HW 기준 구현에
                                의해 발생하는 제약으로부터 발생할 수 있습니다. 
                                일반적인 서멀 드라이버로부터 검출될 수 있는
                                서멀 ACPI 제약 사항들을 포함하여 다루지 않습니다.
                                
여러분이 여러분에게 CPU 동작 주파수를 지정된 값으로 셋팅할 수 있는
“userspace” 가버너를 선택했다면, 여러분은 현재 주파수를 다음에서
읽을 수 있습니다.
scaling_setspeed.               새 주파수를 여기로 “echo함”으로써,
                                여러분은 그 CPU의 속도를 바꿀 수 있습니다.
                                그러나 scaling_min_freq와 scaling_max_freq
                                안의 제약사항안에 있어야 합니다.

[Linux:Kernel] Linux CPUFreq CPU Drivers

이 문서의 저작권은 GPL 라이센스를 따릅니다.(This document is released under the GPL license.)

             리눅스(TM) 커널 내의 CPU 주파수와 전압 조정 코드


                         L i n u x    C P U F r e q

                           C P U   D r i v e r s 

                           – 개발자를 위한 정보 –


                    Dominik Brodowski  <linux@brodo.de>
                번역: 양정석 <dasomoli@gmailREMOVETHIS.com>



   Clock scaling allows you to change the clock speed of the CPUs on the
    fly. This is a nice method to save battery power, because the lower
            the clock speed, the less power the CPU consumes.


차례:
—–
1.   뭘 해야 하나요?
1.1  초기화
1.2  Per-CPU 초기화
1.3  검증
1.4  target을 쓸까, setpolicy를 쓸까?
1.5  target 호출
1.6  setpolicy 호출
2.   주파수 테이블 헬퍼



1. 뭘 해야 하나요?
==================

그래, 여러분이 막 새 브랜드의 CPU / 칩셋을 데이터 시트와 함께 얻게 됐고,
이 CPU / 칩셋을 위한 cpufreq 지원을 추가하고 싶다고요? 좋습니다. 여기에
필요한 것들에 대한 몇 가지 힌트들이 있어요:


1.1 초기화
———-

무엇보다 먼저, __initcall 레벨 7 (module_init()) 이나 그 이후의 함수 안에서
이 커널이 맞는 CPU와 맞는 칩셋 상에서 실행되는지를 확인하세요. 그렇다면,
struct cpufreq_driver 를 CPUfreq 코어와 함께 cpufreq_register_driver()를
사용해서 등록하세요.

이 struct cpufreq_driver 는 무엇을 포함해야 할까요?

cpufreq_driver.name –           이 드라이버의 이름.

cpufreq_driver.owner –          THIS_MODULE;

cpufreq_driver.init –           per-CPU 초기화 함수로의 포인터.

cpufreq_driver.verify –         “검증” 함수로의 포인터.

cpufreq_driver.setpolicy _또는_ 
cpufreq_driver.target –         아래에서 차이에 대해 살펴보세요.

그리고 옵션으로

cpufreq_driver.exit –           per-CPU 클린업 함수로의 포인터.

cpufreq_driver.resume –         A pointer to a per-CPU resume function
                                which is called with interrupts disabled
                                and _before_ the pre-suspend frequency
                                and/or policy is restored by a call to
                                ->target or ->setpolicy.

cpufreq_driver.resume –         pre-suspend 주파수와(또는) 정책이 ->target
                                이나 ->setpolicy 호출로 복구되기 _전에_
                                인터럽트가 꺼진 상태에서 호출되는 per-CPU
                                resume 함수의 포인터.

cpufreq_driver.attr –           sysfs 로 값을 노출시킬 “struct freq_attr”의
                                NULL로 끝나는 리스트의 포인터.


1.2 Per-CPU 초기화
——————

새 CPU가 디바이스 모델과 등록될 때, 또는 cpufreq 드라이버가 그 스스로를
등록한 후에, per-CPU 초기화 함수 cpufreq_driver.init이 호출됩니다.
그건 struct cpufreq_poliy *policy를 인자로 가져옵니다. 이제 뭘 하죠?

필요하면, 여러분의 CPU 상의 CPUfreq 지원을 활성화하세요.

그러면, 그 드라이버가 다음 값들을 채워넣어야만 합니다:

policy->cpuinfo.min_freq _와_
policy->cpuinfo.max_freq –      이 CPU 가 지원하는 최저/최고 주파수(kHZ)
policy->cpuinfo.transition_latency   이 CPU 상에서 두 주파수 사이에
                                변환되는데 걸리는 나노초 시간(적절하다면
                                맞지만, 아니면 CPUFREQ_ETERNAL 지정).

policy->cur                     (적절하다면) 이 CPU의 현재 동작 주파수
policy->min, 
policy->max, 
policy->policy 그리고, 필요하다면,
policy->governor                이 CPU를 위한 “기본 정책”을 반드시 포함해야
                                함. 조금 지나면, cpufreq_driver.verify와
                                다음 둘 cpufreq_driver.setpolicy 나
                                cpufreq_driver.target 중 하나가 이 값들과
                                함께 호출됩니다.

이들 값들 중 몇을 셋팅하기 위해서 주파수 테이블 헬퍼가 도움이 될 겁니다.
자세한 사항은 섹션 2를 보시면 됩니다.

1.3 검증
——–

사용자가 셋팅하려는 (“policy,governor,min,max”로 구성된) 새로운 정책을
결정하면, 이 정책은 맞지않는 값들이 교정될 수 있도록, 반드시 유효성이
검사되어야 합니다. 이들 값의 검증을 위해서 주파수 테이블 헬퍼와(또는)
cpufreq_verify_within_limits(struct cpufreq_policy *policy, unsigned
int min_freq, unsigned int max_freq) 함수가 도움이 될 겁니다. 주파수
테이블 헬퍼에 대한 자세항 사항은 섹션 2를 보시면 됩니다.

여러분은 적어도 한 유효한 주파수(또는 동작 범위)를 policy->min 과
policy->max 안에서 확인할 필요가 있습니다. 필요하다면 policy->max 를
먼저 증가시키고, 이게 해결 방법이 아닐 때만 policy->min 을 감소시키세요.


1.4 target을 쓸까, setpolicy를 쓸까?
————————————

대부분의 cpufreq 드라이버나 대부분의 CPU 주파수 조정 알고리즘조차도
한 주파수로만 CPU를 셋팅할 수 있습니다. 이를 위해서 여러분은
->target 함수를 사용합니다.

어떤 cpufreq 가능한 프로세서들은 주파수를 확실한 그들만의 제약사항 사이에서
변환합니다. 이들은 ->setpolicy 함수를 사용하는 것이 좋습니다.

1.4. target 호출
—————-

target 호출은 세가지 인자를 가집니다: struct cpufreq_policy *policy,
unsigned int target_frequency, unsigned int relation.

CPUfreq 드라이버는 여기에서 불려지는 때에 새 주파수를 반드시 셋팅해야
합니다. 실제 주파수는 다음 규칙을 사용해서 결정되어야만 합니다:

– “target_freq” 에 가깝게 유지
– policy->min <= new_freq <= policy->max (이건 반드시 유효해야 합니다!!!)
– relation==CPUFREQ_REL_L 라면, new_freq를 target_freq와 같거나 더 높게 선택
  하도록 시도합니다. (“더 낮은 이 아닌, 최저(lowest)를 위한 L”)
– relation==CPUFREQ_REL_H 라면, new_freq를 target_freq와 같거나 더 낮게 선택
  하도록 시도합니다. (“더 높은 이 아닌, 최고(highest)를 위한 H”)

여기서 다시, 주파수 테이블 헬퍼는 여러분을 도와줄 수 있습니다 – 자세한
사항은 섹션 2를 보세요.


1.5 setpolicy 호출
——————

setpolicy 호출은 오직 struct cpufreq_policy *policy 만 인자로 가집니다.
여러분은 가장 낮은 프로세서 내부나 칩셋 내부 동적 주파수 변환의 더 낮은
제약사항을 policy->min으로, 더 높은 제약사항을 policy->max로, 그리고
-만약 지원한다면- policy->policy 가 CPUFREQ_POLICY_PERFORMANCE 일 때,
성능 지향형 셋팅을, 그리고 CPUFREQ_POLICY_POWERSAVE 일 때, 전력 절약
형 셋팅을 설정할 필요가 있습니다. 또한 drivers/cpufreq/longrun.c 안의
참고 구현을 확인하세요.



2. 주파수 테이블 헬퍼
=====================

대부분의 cpufreq 프로세서들이 몇 가지 지정된 주파수만 셋팅할 수 있는
것처럼, 이런 동작의 “주파수 테이블”은 그 프로세서 드라이버의 어떤 동작에
도움이 될 것입니다. 앞에서 언급된 “주파수 테이블”은 여러분이 사용하길
원하는 “index”내에 어떤 값을, 그리고 “frequency” 안에 해당하는 주파수로 된
struct cpufreq_freq_table 항목의 배열로 구성되어 있습니다. 테이블의 끝에,
여러분은 cpufreq_freq_table 항목의 frequency에 CPUFREQ_TABLE_END로 셋팅할
필요가 있습니다. 그리고 테이블 안의 한 항목을 그냥 넘기길 원한다면,
frequency를 CPUFREQ_ENTRY_INVALID로 셋팅하면 됩니다. 그 항목이 증가하는
순서로 있을 필요는 없습니다.

cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
                                struct cpufreq_frequency_table *table); 의
호출을 통해 cpuinfo.min_freq와 cpuinfo.max_freq 값들이 검출됩니다. 그리고
policy->min 과 policy->max로 같은 값이 셋팅됩니다. 이것은 per-CPU 초기화
단계에서 유용합니다.

int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
                                   struct cpufreq_frequency_table *table);
는 적어도 한 개의 유효한 주파수가 policy->min과 policy->max 안에 있고,
모든 다른 조건들을 만족한다는 것입니다. 이것은 ->verify 호출에서
유용합니다.

int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
                                   struct cpufreq_frequency_table *table,
                                   unsigned int target_freq,
                                   unsigned int relation,
                                   unsigned int *index);

는 ->target 단계를 위한 맞는 주파수 테이블 헬퍼입니다. 그냥 값들을
이 함수로 넘기면 되고, 그 CPU가 셋팅될 주파수를 포함하는 주파수
테이블 항목의 번호를 unsigned int index로 반환합니다. 알림: 이것은
이 cpufreq_table_entry.index 안의 “index”가 아니고,
cpufreq_table[index] 대신입니다. 그래서 새로운 주파수는
cpufreq_table[index].frequency 이고, 여러분이 주파수 테이블 “index”
필드로 저장한 그 값은 cpufreq_table[index].index 입니다. [*]

* 역자 주: 주파수 테이블의 index 라는 이름이 혼동스러워서 driver_data 로
이름이 변경되었습니다. 그래서 이 줄은 문서에서 삭제되었습니다.

[Linux:Kernel] Linux CPUFreq Governor

이 문서의 저작권은 GPL 라이센스를 따릅니다(This document is released under the GPL license).

              리눅스(TM) 커널 안의 CPU 주파수와 전압 조정 코드
                         L i n u x    C P U F r e q

                      C P U F r e q   G o v e r n o r s

                      – 사용자와 개발자들을 위한 정보 –

                    Dominik Brodowski  <linux@brodo.de>
                  추가와 교정은 Nico Golde <nico@ngolde.de>
                 번역 : 양정석 <dasomoli@gmailREMOVETHIS.com>
   Clock scaling allows you to change the clock speed of the CPUs on the
    fly. This is a nice method to save battery power, because the lower
            the clock speed, the less power the CPU consumes.
차례:
—–
1.   CPUFreq 가버너가 뭔가요?

2.   리눅스 커널 안의 가버너들
2.1  성능(Performance)
2.2  전력절약(Powersave)
2.3  사용자공간(Userspace)
2.4  수요충족(Ondemand)
2.5  보수적(Conservative)
2.6  상호적(Interactive)

3.   CPUfreq 코어 안의 가버너 인터페이스

1. CPUFreq 가버너가 뭔가요?
===========================

대부분의 cpufreq 드라이버들(사실, longrun 하나를 빼고 모두다) 또는 대
부분의 cpu 주파수 조정 알고리즘조차 오직 CPU에 하나의 주파수를 셋팅
하는 것만을 제공합니다. 동적인 주파수 조정을 제공함에 따라 cpufreq
코어는 한 “목표 주파수”의 이들 드라이버들을 말할 수 있어야만 합니다.
그래서 이들 지정된 드라이버들은 원래 있던 “->setpolicy” 호출 대신에
“->target” 호출을 제공하도록 바뀔 것입니다. “longrun”을 위해 모두가
같게 머물긴 하겠지만 말입니다.

CPUFreq 정책 안에서 무슨 주파수가 사용되어져야 하는 지는 어떻게 결정할
까요? 그건 “cpufreq 가버너”를 사용해서 합니다. 이 패치에는 이미
두 개가 있습니다– 주파수를 정적으로 가장 낮게 또는 가장 높은 주파수로
설정하는 “powersave”와 “performance” 가 이미 각각 있습니다.
적어도 둘 이상의 이같은 가버너가 수시일 내에 추가될 준비가 될 겁니다.
그러나 동적 주파수 조정에 관한 수많은 다른 이론과 모델들이 있는 것처럼
더 많이 될 것 같아 보입니다. cpufreq로서 그런 일반적인 인터페이스의
사용은 조정 가버너들에게 이들은 널리 테스트될 수 있다는 것과, 각각의 특정
용도에 대해 선택될 수 있는 가장 좋은 것을 제공합니다.

기본적으로, 다음 흐름도를 따릅니다:

CPU는 기정된 “제한사항”안에서 독립적으  |        CPU는 지정 주파수로만
로 스위칭될 수 있음                     |           셋팅될 수 있음

                                  “CPUfreq 정책”
                은 주파수 제한(policy->{min,max})과 사용될 CPUFreq로
                                   구성됩니다
                         /                    \
                        /                      \
                       /                       cpufreq 가버너가 (동적으로 혹은
                      /                         정적으로) policy->{min,max}의
                     /                         제한 사항안에서 무슨 target_freq를
                    /                          사용할 지 결정합니다.
                   /                                \
                  /                                  \
        ->setpolicy 호출을 사용하여,            ->target 호출을 사용하여,
         제한 사항과 “정책”을 셋팅.              가장 가까운 주파수를 target_freq
                                                 로 셋팅. policy->{min,max} 안에
                                                 있음이 보장됨.

2. 리눅스 커널 안의 가버너들
============================

2.1 성능(Performance)
———————

CPUfreq 가버너 “performance”는 CPU를 정적으로 scaling_min_freq 와
scaling_max_freq 경계 안에서 가장 높은 주파수로 셋팅합니다.
2.2 전력절약(Powersave)
———————–

CPUfreq 가버너 “powersave”는 CPU를 정적으로 scaling_min_freq 와
scaling_max_freq 경게 안에서 가장 낮은 주파수로 셋팅합니다.
2.3 사용자공간(Userspace)
————————-

CPUfreq 가버너 “userspace”는 사용자에게, 또는 UID “root”로 실행되는
어떤 사용자공간 프로그램에게 CPU-device 디렉토리 안에 이용가능한
“scaling_setspeed” sysfs 파일을 만듦으로써 CPU를 지정된 주파수로
셋팅할 수 있도록 합니다.
2.4 수요충족(Ondemand)
———————-

CPUfreq 가버너 “ondemand” 는 현재 사용량에 따라 CPU를 셋팅합니다.
이를 수행하기 위해 CPU는 매우 빠르게 주파수를 바꿀 수 있는 능력을
가져야 합니다. 접근 가능한 파라메터 sysfs 파일이 몇 개 있습니다:

sampling_rate: uS(10^-6 초)로 측정됨, 이것은 얼마나 자주 여러분이 커널이
CPU 사용량을 살펴보고 주파수에 관해 무엇을 할 것인지에 대한 결정을 내리길
원하는지 입니다. 일반적으로 이것은 ‘10000’ 주변이나 그 이상 값으로 셋팅
됩니다. 기본값은 (users-guide.txt와 절충하여):
transition_latency * 1000
전이 지연 시간은 ns 이고 sampling_rate는 us 임을 명심하세요. 그래서 여러분은
기본적으로 같은 sysfs 값을 얻을 수 있습니다.
샘플링 레이트는 언제나 전이 지연 시간을 고려해서 조정되어야만 합니다.
bash 에서 샘플링 레이트를 전이 지연 시간의 750 배 높은 값(말했듯이, 기본값은
1000)으로 셋팅하려면:
echo `$(($(cat cpuinfo_transition_latency) * 750 / 1000)) \
    >ondemand/sampling_rate

sampling_rate_min:
샘플링 레이트는 HW 전이 지연 시간에 의해 제한됩니다:
transition_latency * 100
또는 커널 제한에 의해서요:
CONFIG_NO_HZ 가 셋팅되면, 제한은 10ms 고정값.
CONFIG_NO_HZ 가 셋팅되지 않거나 부트 파라미터로 nohz=off 가 사용되면,
그 제한은 CONFIG_HZ 옵션에 의해 결정됩니다:
HZ=1000: min=20000us  (20ms)
HZ=250:  min=80000us  (80ms)
HZ=100:  min=200000us (200ms)
커널의 가장 높은 값과 HW 전이 지연 제한이 나타나고, 가장 작은 샘플링 레이트
가 사용됩니다.

up_threshold: 주파수를 증가시키는 게 좋을지에 대한 결정을 커널이 내리는데
필요한 ‘sampling_rate’의 샘플링들 사이의 평균 CPU 사용량으로 정의됩니다.
예를 들면, 그 값이 ’95’로 셋팅되어 있을 때는 검사 간격 사이에 CPU가 평균
95% 이상 사용 중이면 CPU 주파수를 증가시킬 필요가 있다는 결정을 함을
의미합니다.

ignore_nice_load: 이 파라미터는 ‘0’ 또는 ‘1’ 을 값으로 가집니다.
‘0’ 으로 셋팅되었을 때(기본값)는 모든 프로세스들이 ‘CPU 활용도’ 값을 위해
세어집니다. ‘1’ 로 셋팅되었을 때는 ‘nice’ 값으로 실행되는 프로세스들은
전체 사용량 계산에 같이 세어지지 않습니다. 이 것은 여러분이 여러분의
랩탑에서 ‘nice’ 를 사용하여 끝나는 시간이 얼마나 오래 걸릴지를 걱정하지
않는 CPU를 많이 사용하는 심한 계산을 실행 중일 때 유용하고, 여러분의
CPU 주파수를 증가시키는데 그 프로세스가 영향을 미치는 것을 막아줍니다.

sampling_down_factor: 이 파라미터는 커널이 최고 속도에서 실행 중인 동안
주파수를 언제 감소시킬 것인지를 결정하는 속도을 제어합니다. 1(기본값)로
셋팅되었을 때는 다시 부하를 평가하기 위한 결정이 현재 클럭 속도와 상관없이
같은 간격에서 이루어 집니다. 그러나 1 보다 크게(예를 들어, 100) 셋팅되면
CPU가 높은 부하로 인해 그 최소 속도로 있을 때, 부하의 재평가를 위한
스케줄링 간격의 배수로서 수행됩니다. 이것은 부하 평가의 과부하를 줄임으로써
성능을 향상시키고, CPU 가 정말 바쁠 때 다시 느려졌다가 빨라지는 것보다 나은,
그 최고 속도를 유지하도록 도움을 줍니다. 이것은 낮은 속도/낮은 CPU 부하량의
동작에는 영향을 주지 않습니다.
2.5 보수적(Conservative)
————————

“ondemand”와 매우 비슷한, CPUfreq 가버너 “conservation” 는 현재 사용량에
따라 CPU 를 셋팅합니다. 그것은 동작 상에서, 어떤 CPU 상의 부하가 있는
순간 최고 속도로 점프하는 것보다는 우아하게 CPU 속도를 증가시키고
감소시킨다는 것이 다릅니다. 이 동작은 배터리 전원 환경에 더 잘어울립니다.
이 가버너는 다음의 몇 개 추가된 sysfs를 통해 “ondemand” 가버너와 같은
방식으로 조작할 수 있습니다:

freq_step: 이것은 CPU 주파수가 그에 의해 부드럽게 중가되거나 감소되어야
하는지 백분율로 표시된 단계를 나타냅니다. 기본적으로 CPU 주파수는 여러분의
CPU 최고 주파수의 5% 단위로 증가할 것입니다. 여러분은 이 값은 어느 곳에서나
0과 100사이에서 바꿀 수 있습니다. ‘0’은 그 부하에 상관없이 어느 속도로
여러분의 CPU 속도를 효과적으로 고정시킬 것입니다. 반면 ‘100’은 이론적으로
“ondemand” 가버너와 동일하게 동작하도록 합니다.

down_threshold: “ondemand” 가버너에서 찾을 수 있는 ‘up_threshold’ 와 같지만,
방향은 반대입니다. 예를 들면, 그 기본값이 ’20’으로 셋팅되었을 때는 그
주파수를 낮추려면 CPU 사용량이 샘플링 간격 사이에 20% 아래일 필요가 있다는
의미입니다.

2.6 상호적(Interactive)
———————–

CPUfreq 가버너 “interactive”는 지연 시간에 민감한 상호적 작업 부하에
맞추어 설계되었습니다. 이 가버너는 CPU 속도를 “ondemand” 와
“conservative” 가버너와 비슷하게, 사용량에 따라 셋팅합니다. 그러나
설정가능한 동작들이 다릅니다.

이 가버너를 위해 맞출 수 있는 값들은 다음과 같습니다:

target_loads: CPU 부하 값은 현재 CPU 부하를 그 값으로 맞추기 위해서
속도를 조정하는데 사용됩니다. 일반적으로, 목표 부하값이 낮을수록
더 자주 그 가버너가 목표 아래로 부하를 낮추기 위해 CPU 속도를
끌어올릴 것입니다. 그 형식은 하나의 목표 부하값, 그 다음 옵션으로
목표하거나 그 이상의 속도를 위한 CPU 부햐와 CPU 속도의 짝입니다.
콜론이 속도, 그리고 그와 관련된 목표 부하량을 읽기 쉽게 하기 위해
사용될 수 있습니다. 예를 들면:

   85 1000000:90 1700000:99
   
CPU 부하가 1GHz 이하에서는 85%를 목표로 하고, 90%는 1GHz에서나 그 이상
1.7GHz까지, 그리고 그 이상은 99%를 목표로 합니다. 속도가 지정되면
이들은 증가하는 순서로 나와야 합니다. 높은 목표 부하값들은 일반적으로
높은 속도로 지정되고, 그래서 목표 부하값 또한 보통 증가하는 순서로
나타납니다. 기본값은 모든 속도에 목표 부하 90% 입니다.
min_sample_time: 낮추기 전에 현재 주파수에서 소비할 시간의 최소량.
기본값은 80000 uS.

hispeed_freq: gp_hispeed_load 로 지정된 값에 CPU 부하가 도달했을 때
처음에 증가하는 중간급의 “처음 만나는 속도”. 부하가 above_hispeed_delay에
지정된 시간의 양 동안 높게 유지되면, 속도는 더 빨라집니다. 기본값은
가버너의 초기화 시간에 그 정책에 의해 허용되는 최고 속도입니다.

go_hispeed_load: hispeed_freq 로 올라가는 CPU 부하. 기본은 99%.

above_hispeed_delay: 속도가 hispeed_freq 혹은 그 이상일 때, 계속되는
고부하로 인해 속도를 올리기 전에 이 시간만큼 대기합니다.
이 형식은 하나의 대기 시간 값, 그 다음 옵션으로 CPU 속도와 이들 속도
혹은 그 이상의 속도에서 사용되는 대기 시간의 짝이 따릅니다. 콜론이
읽기 쉽게 하기 위해 속도와 그 연관된 대기 시간 사이에 사용될 수
있습니다. 예를 들면:

   80000 1300000:200000 1500000:40000

CPU 속도 1.3 GHz 까지는 80000 uS 대기 시간이 사용되고, 1.5 GHz
속도까지는 200000 uS가 속도 대기 시간으로, 1.5 GHz(그리고 그 이상)
에서는 40000 uS 대기 시간이 사용됩니다. 속도들이 지정되면 이들은
증가하는 순서로 나타나야 합니다. 기본값은 20000 uS.

timer_rate: CPU가 대기 상태가 아닐 때 CPU 부하를 재평가하기 위한
샘플링 속도. 한 개의 미룰 수 있는 타이머가 사용되는데, 어떤 다른 것을
실행될 필요가 있을 때까지 CPU는 대기 상태로부터 이 타이머를 수행할
때까지 깨어나지 않게 됩니다. (최하 속도에서 실행되지 않을 때 이
타이머를 미룰 수 있는 최대 시간은 timer_slack을 통해 설정 가능합니다)
기본값은 20000 Us.

timer_slack: 최하 속도 이상의 속도로 실행 중일 때, timer_rate를 넘어
가버너의 샘플링 타이머의 처리를 미룰 수 있는 최대 추가 시간. CPU들이
최하보다 높은 속도로 실행 중일때 대기 상태에서 추가 전력을 소비하는
플랫폼을 위해 이것은 타이머가 얼마나 오래 부하 재평가와 속도를
떨어뜨리는 것의 순위를 미룰 것인가 상한을 둡니다. 예를 들면, timer_rate
가 20000uS 이고 timer_slack 이 10000uS 이면, 타이머는 최하 속도에 있지
않을 때, 최대 30msec 까지 수행을 미룰 것입니다. -1 값은 타이머를 모든
속도에서 무한히 미루겠다는 뜻입니다. 기본은 80000 uS.

boost: 0이 아니면, 즉시 모든 CPU들의 속도를 이 속성에 0이 쓰여질 때까지
적어도 hispeed_freq 까지 일시적으로 올립니다. 0이면, 보통의 부하에
따라 CPU 속도를 hispeed_freq 아래로 떨어지는 것이 허용됩니다.
기본값은 0.

boostpulse: 쓰여질 때마다, 즉시 모든 CPU들의 속도를 적어도
boostpulse_duration에 지정된 시간 동안 hispeed_freq로 일시적으로
올리고, 그 후에 보통의 부하에 따라 hispeed_freq 아래로 속도가 떨어지는
것이 허용됩니다.

boostpulse_duration: boostpulse에 쓰여질 때 보통의 부하에 따라 속도를
떨어뜨리는 것을 허용하기 전에 hispeed_freq 에서 CPU 속도를 유지하는
시간의 길이. 기본값은 80000 uS.
3. CPUfreq 코어 안의 가버너 인터페이스
======================================

새로운 가버너는 그 자신을 CPUfreq 코어에 “cpufreq_register_governor”를
사용해서 반드시 등록해야 합니다. 그 함수로 전달될
struct cpufreq_governor 는 다음 값들을 반드시 가져야 합니다:

governor->name –            이 가버너의 유일한 이름
governor->governor –        가버너 콜백 함수
governor->owner –           (적절하다면) 가버너 모듈을 위한 .THIS_MODULE

governor->governor 콜백은 그 CPU를 위한 현재의(또는 셋팅될)
cpufreq_policy 구조체, unsigned int인 event와 함께 호출됩니다. 다음의
event들이 현재 정의되어 있습니다:

CPUFREQ_GOV_START:   이 가버너가 그 CPU policy->cpu를 위해 그 의무를
                     시작할 것입니다.
CPUFREQ_GOV_STOP:    이 가버너가 그 CPU policy->cpu를 위해 그 의무를
                     멈출 것입니다.
CPUFREQ_GOV_LIMITS:  CPU policy->cpu를 위한 제한 사항들이 policy->min
                     과 policy->max로 바뀌었습니다.

여러분이 여러분의 드라이버의 다른 “이벤트들”을 외부적으로 필요로 한다면,
CPUFreq 코어가 적절한 락킹을 보장하도록 _오직_
cpufreq_governor_l(unsigned int cpu, unsigned int event) 호출만 사용하도록
하세요.
CPUfreq 가버너는 아마 이들 두 함수 중 하나를 사용해서 CPU 프로세서
드라이버를 호출할 것입니다:

int cpufreq_driver_target(struct cpufreq_policy *policy,
                                 unsigned int target_freq,
                                 unsigned int relation);

int __cpufreq_driver_target(struct cpufreq_policy *policy,
                                   unsigned int target_freq,
                                   unsigned int relation);

target_freq 는 물론, policy->min과 policy->max 안에 있어야만 합니다.
이들 두 함수간에 무슨 차이가 있을까요? 여러분의 가버너가 여전히
governor->governor 로 호출의 직접적인 코드 경로 안에 있다면, per-CPU
cpufreq lock 이 cpufreq 코에 안에서 여전히 잡혀 있을 것이고, 다시
잠글 필요가 없습니다(사실 이렇게 하면 데드락의 원인이 됩니다). 그래서
이런 경우에는 __cpufreq_driver_target 만 사용하세요. 다른 모든 경우에는
(예를 들면, 매 초마다 깨어나는 “데몬화된” 함수가 있을 때), 그 명령이
cpufreq 프로세서 드라이버로 전달되기 전에 cpufreq per-CPU lock을
락킹하기 위해서 cpufreq_driver_target을 사용하세요. 

[Linux:Kernel] Linux CPUFreq Core

이 문서의 저작권은 GPL License를 따릅니다(This document is released under the GPL license).

  리눅스(TM) 커널안의 CPU 동작속도와 전압 조절 코드 
        L i n u x    C P U F r e q
 C P U F r e q    C o r e
   Dominik Brodowski  <linux@brodo.de>
    David Kimdon <dwhedon@debian.org>
번역 : 양정석 <dasomoli@gmailREMOVETHIS.com>

   클럭 조정은 동작하고 있는 CPU의 클럭 속도를 바꿀 수 있게 합니다. 이 것은

    배터리 파워를 절약할 수 있는 좋은 방법입니다. 왜냐하면 클럭 속도가
   낮을수록 CPU가 소비하는 전력도 낮아지기 때문입니다.

    

차례:

—–

1.  CPUFreq 코어와 인터페이스

2.  CPUFreq 노티파이어(notifires)

1. 일반적인 정보

================

CPUFreq 코어 코드는 drivers/cpufreq/cpufreq.c 안에 있습니다. 이 cpufreq

코드는 CPUFreq 구조 드라이버(실제 주파수 전이를 수행하는 코드 조각)를

위한 표준화된 인터페이스, “노티파이어(notifires)”를 제공합니다. 이들은 정책 변경

(예를 들면, ACPI 같은 온도 모듈), 모든 동작 속도 변화(예를 들면,

타이밍 코드)의 알림을 필요로 하거나, 혹은 일정 속도 제한을 강제할 필요가

있는(예를 들면, ARM 아키텍처의 LCD 드라이버 같은) 디바이스 드라이버거나

혹은 커널의 다른 부분 입니다. 추가적으로, 커널 “상수” loops_per_jiffy는

여기 주파수 변경 상에서 업데이트 됩니다.

레퍼런스 카운트는 cpufreq 프로세서 드라이버가 코어와 함께 정확히

등록되었고, cpufreq_put_cpu가 호출되기 전까지 로딩되지 않을 것임을

확실하게 해주는 cpufreq_get_cpu와 cpufreq_put_cpu에 의해서 수행됩니다.

2. CPUFreq 노티파이어(notifires)

================================

CPUFreq 노티파이어는 표준 커널 노티파이어 인터페이스를 따릅니다.

노티파이어에 대한 자세한 사항은 linux/include/linux/notifire.h 를

보세요.

두가지 CPUFreq 노티파이어-정책 노티파이어와 전이 노티파이어-가 있습니다.

2.1 CPUFreq 정책 노티파이어

—————————

새 정책이 셋팅되려고 할 때 이것들이 알려집니다. 각 CPUFreq 정책 노티파이어는

정책의 전이 동안 세 번 호출 됩니다:

1.) CPUFREQ_ADJUST 동안 모든 CPUFreq 노티파이어는 이를 봐야 할 필요가 있다면

   그 제한 사항-온도에 대한 고려나 하드웨어 제한 사항-을 변경할 것입니다. 

2.) CPUFREQ_INCOMPATIBLE 동안 하드웨어 실패를 피하기 위한 변경들만 수행될

   것입니다.

3.) 그리고 CPUFREQ_NOFITY 동안 모든 노티파이어들은 새 정책-만약 두 하드웨어

   드라이버가 이 단계 전에 새 정책에 대해 동의하는데 실패했다면, 그 호환될 수

   없는 하드웨어는 꺼지고 사용자에게 이를 알릴 것입니다-을 알립니다.

이들 단계는 노티파이어의 두번째 인자로 지정됩니다.

세번째 인자, void * 포인터는 다섯 개의 값으로 구성된  cpufreq_policy 구조체를

가리킵니다: cpu, min, max, policy와 max_cpu_freq. min과 max는 새 정책의 

주파수의 상한과 하한 값(kHz) 을, policy는 새 정책, cpu는 영향을 미칠 CPU의

번호, 그리고 max_cpu_freq 는 최고로 지원하는 CPU 주파수입니다. 이 값은

정보 제공 목적으로만 주어집니다.

2.2 CPUFreq 전이 노티파이어

—————————

이 것들은 CPUFreq 드라이버가 CPU 코어 주파수를 바꿀 때와 이 변경이 어떤 외부

영향을 가질 때, 두 번 알려집니다.

두번째 인자는 이들 단계-CPUFREQ_PRECHANGE나 CPUFREQ_POSTCHANGE-를 지정합니다.

세번째 인자는 다음 값들을 가지는 cpufreq_freq 구조체입니다:

cpu
– 영향을 미치는 CPU 번호

old
– 이전 주파수

new
– 새 주파수

시스템이 suspend된 동안 cpufreq 코어가 주파수의 변경을 알아차리면,

이들 노티파이어는 두번째 인자로 CPUFREQ_RESUMECHANGE와 함께 호출됩니다.


 

[Linux:Kernel] Kernel 너무 일찍 죽을 때 Console Log message

1. __log_buf 가 kmsg log buffer. T32 attach 후 다음과 같이 dump 뜰 수 있다(__log_buf가 0xc060eaa4 일 때).

d.save.binary d:\log_ll.log 0xc060eaa4++0x200000

2. console이 Enable 되기 전에 죽는다면, Kernel hacking -> Kernel low-level debugging functions (read help!) (DEBUG_LL [=y]) 를 켜면 메시지를 볼 수 있다. 서브 메뉴의 UART 번호는 맞춰줘야 함!

[Linux] vmlinux -> Image

명령어만 덜렁 써놓기 뭐해서 설명을 덧붙인다.
가끔 undefined instrunction 예외가 날 때, 코드 메모리의 이상 여부를 확인해야 할 때가 있다.
커널은 알다시피 zImage를 Decompressed 하여 메모리상에 올린 후 실행하는데, 그 Decompressed Image가 Image 이다. Image는 커널의 빌드 과정에서 아래와 같이 objcopy를 이용해서 만든다. Makefile 을 참고해보면 알 수 있을 것이다. ARM의 경우는 arch/arm/boot/ 와 그 아래의 Makefile을 살펴보면 된다.
Android JB MR1의 경우 아래 경로의 prebuilt 된 툴체인을 사용한다.

prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-objcopy -O binary -R .comment -S vmlinux arch/arm/boot/Image

나온 Image를 Trace32로 실제 커널 메모리를 dump 해서 Binary Diff 해보면 메모리의 H/W적인 이상여부나 코드 메모리를 어디서 건드려서 깨지진 않았는지 확인해 볼 수 있다.
커널 프로그램이 물리메모리 0x40008000과 같은 주소에 로딩되므로, 특정 모듈이나 특정 루틴의 경우 objcopy로 걸러낸 후, 해당 주소의 프로그램을 실제 메모리에서 offset을 뺀 값으로 Image파일에서 찾아야 한다.

Windows에서는 HxD와 같은 툴로 Binary Diff 할 수 있다. Beyond compare를 써도 되고(근데 유료라는 점)…

[Linux kernel] GPIO 정리

lwn.net의 GPIO in the kernel: an introductionGPIO in the kernel: future directions 를 보고 나름의 정리를 해둔다.

1. 현재 GPIO의 Kernel Internal API

GPIO를 가지고 뭔가 하기 위해서 다음 헤더 파일을 include 한다.


#include <linux/gpio.h>

현재의 커널은 모든 GPIO를 unsigned integer로 나타낸다. 그래서 platform data나 device tree를 통해 GPIO 번호를 넘기는 것이 가능하다.

GPIO는 사용 전에 allocation 되어야 한다. 현재 구현은 이를 강제하고 있지는 않다. allocation 은 다음 함수를 이용한다.


int gpio_reqeust(unsigned int gpio, const char *label);

label은 나중에 sysfs 로 나타날 수 있다. 반환값 0은 성공, 다른 값은 음수로 에러 번호를 반환한다. 다음을 통해 GPIO를 다시 돌려줄 수 있다.


void gpio_free(unsigned int gpio);

몇 가지 변형이 있는데 gpio_request_one() 은 초기 설정을 같이 할 수 있고, gpio_request_array() 는 몇 개의 GPIO를 한번에 설정하면서 request 할 수 있다. “managed” 버전(예를 들면, devm_gpio_request())은 개발자가 잊어버렸을 때 cleanup을 자동적으로 처리한단다(managed 버전이 있는 건 몰랐네…).

GPIO가 입력으로 사용되면,


int gpio_direction_input(unsigned int gpio);


출력으로 사용되면,


int gpio_direction_output(unsigned int gpio, int value);

output 일 때 value는 꼭 0 이나 1로 지정되어야 한다. 둘 다 성공 시에는 0을, 아니면 음수로 에러 번호를 반환한다.

GPIO 입력값을 읽을 때는,


int gpio_get_value(unsigned int gpio);

에러가 발생하려면 gpio_direction_input()을 호출했을 때 에러가 발생한다고 생각하기 때문에 별도 에러 체크는 하지 않는다. 그러므로 gpio_direction_input()의 반환값을 꼭 체크해야 한다.

GPIO 출력값을 설정할 때는 gpio_direction_output()을 사용할 수도 있지만, 이미 출력모드로 되어 있으면, 다음을 사용하는게 더 낫다.


void gpio_set_value(unsigned int gpio, int value);


몇몇 GPIO 컨트롤러는 GPIO 입력 값이 바뀌면 인터럽트를 걸어주는데, 이 IRQ 번호를 얻고 싶으면,


int gpio_to_irq(unsigned int gpio);

여기서의 gpio는 gpio_request() 로 꼭 얻어야 하고, gpio는 일단 입력 모드로 된다. irq 번호 대신 음수로 된 에러 번호가 반환될 수 있다. 반환된 irq는 request_irq()로 인터럽트 핸들러를 셋팅할 수 있다.

GPIO를 sysfs로 export 해서 user space에서 제어할 수 있도록 하려면,


int gpio_export(unsigned int gpio, bool direction_may_change);

direction_may_change는 보이는 것처럼, user space에서 direction을 바꿀 수 있는지 셋팅해주기 위한 것이다. 안하는 게 낫다. gpio_unexport() 로 sysfs를 없앨  수 있고, gpio_export_link() 를 사용하면 다른 이름으로 export 할 수도 있다.

더 많은 사항은 Documentation/gpio.txt 를 참고.

2. Descriptor-based API (gpiod_*)

현재의 GPIO API 가 integer를 사용하는데, 이 대신에 descriptor-based GPIO 인터페이스를 제공하는 방법이다. 이를 위해 struct gpio_desc * 포인터 타입을 사용한다. 이 인터페이스에 대한 반응은 꽤 좋다고 한다. 거의 곧 머지될 거 같다나..
현재 GPIO API와 매우 비슷하다.


#include <linux/gpio/consumer.h>

int gpiod_direction_input(struct gpio_desc *desc);
int gpiod_direction_direction_output(struct gpio_desc *desc, int value);
int gpiod_get_value(struct gpio_desc *desc);
void gpiod_set_value(struct gpio_desc *desc, int value);
int gpiod_to_irq(struct gpio_desc *desc);
int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
int gpiod_export_link(struct device *dev, const char *name, struct gpio_desc *desc);
void gpiod_unexport(struct gpio_desc *desc);


gpio_ prefix 대신 gpiod_ prefix를 사용하고 GPIO 번호 integer대신 struct gpio_desc * 를 사용한다.

GPIO 번호로 descriptor를 얻을 수도 있다.


struct gpio_desc *gpio_to_desc(unsigned gpio);

반대인 desc_to_gpio() 도 있다. desc로 gpio 번호를 얻으면 포인터에서 얻어진 것이므로 현재의 기존 GPIO API에 안심하고 쓸 수 있다. 그러나 GPIO 번호로 descriptor를 얻는 건 별로 좋지 않다. 그래서 다음을 제공한다.


struct gpio_desc *gpiod_get(struct device *dev, const char *name);

dev는 GPIO 라인을 제공하는 device여야 하고, “name”은 라인을 말한다.
GPIO 라인 접근을 제거하기 위해서 gpiod_put() 도 제공한다.

3. Block GPIO

위에 설명한 것들은 개별 GPIO 라인을 관리하는데 초점을 둔다. 근데 GPIO들은 그룹으로 함께 쓰일 때가 많다.
어떤 하드웨어들은 또 한번의 I/O 메모리 write 연산으로 여러 라인을 동시에 바꿀 수 있다. 그래서 여러 GPIO를 하나의 그룹처럼 조작할 때, 하나의 블록으로 엮어서 사용하기 위해 Block GPIO 패치가 시도되었다. Descriptor-based GPIO API 에 비하면 별로 크게 다루어지지는 않았다.


struct gpio_block *gpio_block_create(unsigned int *gpios, size_t size, const char *name);

gpios는 하나의 블록으로 그룹지어지는, GPIO 번호들의 size 크기의 Array 이다. name은 user spcae에서 그 블록으로 동작하는데 사용될 수 있다. gpios 안의 GPIO 들은 gpio_request()로 이전에 이미 요청되어져 있어야 하고, 그 direction 도 각각 셋팅되어져 있어야 한다. GPIO 들이 흩어져 있거나, 드라이버가 Internal Block APIO를 구현하지 않으면, 그냥 지금처럼 개별 라인으로 접근한다.

GPIO 블록의 조작은,


unsigned long gpio_block_get(struct gpio_block *block, unsigned long mask);
void gpio_block_set(struct gpio_block *block, unsigned long mask, unsigned long values);

mask 로 블록 안의 GPIO를 고를 수 있는데, mask는 위의 gpio_block_create() 로 전달되는 array에 해당하는 비트가 쓰인다. 여기서 알 수 있는 점은 한 개 블록의 GPIO 의 갯수는 long의 비트 수까지만 될 수 있다는 점이다.
gpio_block_get() 은 가능하면 한꺼번에 지정된 라인들을 읽고, 비트 마스크로 결과를 반환한다. gpio_block_set()은 한꺼번에 셋팅할 수 있다.

GPIO 볼록은 다음으로 제거 가능하다.


void gpio_block_free(struct gpio_block *block);


User space에서 sysfs 로 GPIO 블록을 셋팅하거나 읽을 수 있도록하는, 등록 함수도 있다.


int gpio_block_register(struct gpio_block *block);
void gpio_block_unregister(struct gpio_block *block);

등록하면 gpio_block_create()에서 사용한 이름으로 device_node도 생성된다. 그 디바이스를 읽으면, 블록 안의 GPIO의 상태를 반환하고, 쓰면, 그에 따른 GPIO를 셋팅할 수도 있다. read, write 동작에 사용하는 mask를 셋팅하는데-커맨드 번호로 0을 사용- ioctl() 도 제공한다.

[Linux kernel] Softlockup 디텍터와 (nmi_watchdog로 알려진) hardlockup 디텍터

이 문서의 저작권은 GPL을 따릅니다(This document is released under the GPL license).

번역 : 양정석(dasomoli@gmailREMOVETHIS.com)

===============================================================

Softlockup 디텍터와 (nmi_watchdog로 알려진) hardlockup 디텍터
===============================================================
리눅스 커널은 soft와 hard lockup을 검출하기 위해서 watchdog처럼 동작할
수 있습니다.
‘softlockup’ 은 커널로부터 야기되는 다른 태스크들에게 실행할 기회를
주지 않고 커널 모드 안에서 20초 이상 도는 버그로 정의(자세한 사항은
아래 “구현” 참조)됩니다. 기본값으로 검출된 상태의 현재 스택 트레이스를
보여주고, 시스템은 멈춘 상태로 머물게 됩니다. 아니면 다르게 커널이 패닉
을 일으키도록 설정될 수도 있습니다; 이를 위해, sysctl의
“kernel.softlockup_panic”, 커널 파라미터의 “softlockup_panic”, 그리고
컴파일 옵션 “BOOTPARAM_HARDLOCKUP_PANIC”이 제공됩니다.
‘hardlockup’ 은 CPU로부터 야기되는 다른 인터럽트들이 실행할 기회를
주지 않고 커널 모드 안에서 10초 이상 도는 버그로 정의(자세한 사항은
아래 “구현” 참조)됩니다. softlockup 상황과 비슷하게, 기본값은 컴파일
타임 옵션의 “BOOTPARAM_HARDLOCKUP_PANIC”, 커널 파라미터의
“nmi_watchdog”(자세한 사항은 “Documentation/kernel-parameters.txt”
참조)을 통해 바꿀 수 있는데, 바뀌지 않는 한, 검출 상태의 현재 스택
트레이스를 보여주고, 시스템은 멈춘 상태로 머물게 됩니다. 
패닉 옵션은 지정된 시간이 지난 후에 시스템을 자동으로 리부팅하기 위해서
panic_timeout(이 timeout 은 헷갈리게 이름지어진 “kernel.panic” sysctl을
통해 셋팅됩니다)의 조합으로 사용될 수 있습니다.
=== 구현 ===
soft와 hard lockup 디텍터는 각각 hrtimer와 perf 서브시스템의 위에
빌드됩니다. 이의 직접적인 결과는 이론적으로 이들 서브 시스템이 제공되는
어떤 아키텍처 위에서도 동작한다는 것입니다.
주기적인 hrtimer는 인터럽트를 일으키고 watchdog 태스크를 수행(kick)하기
위해서 실행됩니다. NMI perf 이벤트는 매 (컴파일 타임에 10으로 초기화되고
같은 이름의 sysctl을 통해 설정될 수 있는)”watchdog_thresh” 초마다
hardlockup을 검사하기 위해서 생성됩니다. 시스템 안의 어떤 CPU가 그 
시간 동안 hrtimer 인터럽트를 받지 못한다면 ‘hardlockup 디텍터'(NMI perf
이벤트 핸들러)가 설정에 따라, 커널 경고를 생성하거나 패닉을 호출할
것입니다.
watchdog 태스크는 스케줄될 때마다 타임 스탬프를 업데이트 하는 최고
우선 순위 커널 스레드입니다. 타임 스탬프가 2 * watchdog_thresh 초
(softlockup threshold)동안 업데이트되지 않으면, 만약 패닉을 일으키도록
되어 있다면 패닉을 호출하고, 아니면 다른 커널 코드의 실행을 재개한 후에
(hrtimer 콜백 함수 안에 작성된) ‘softlockup 디텍터’가 유용한 디버그 정보를
시스템 로그로 덤프할 것입니다.
hrtimer의 주기는 hardlockup 디텍터가 수행되기 전에 인터럽트 발생을 위한
두번 혹은 세번의 기회를 가지는 2 * watchdog_thresh / 5 입니다.
위에 설명된 대로, 관리자가 hrtimer와 perf 이벤트의 주기를 설정할 수 있도록
커널 옵션이 제공됩니다. 각 환경에 맞는 값은 lockup을 위한 빠른 응답과 검출
오버헤드 사이의 트레이드 오프입니다.