이 문서의 저작권은 GPL을 따릅니다.(This document is released under the GPL license.)
[카테고리:] Development
[Linux:Kernel] Linux CPUFreq CPU Drivers
이 문서의 저작권은 GPL 라이센스를 따릅니다.(This document is released under the GPL license.)
* 역자 주: 주파수 테이블의 index 라는 이름이 혼동스러워서 driver_data 로
이름이 변경되었습니다. 그래서 이 줄은 문서에서 삭제되었습니다.
[Linux:Kernel] Linux CPUFreq Governor
이 문서의 저작권은 GPL 라이센스를 따릅니다(This document is released under the GPL license).
C P U F r e q G o v e r n o r s
– 사용자와 개발자들을 위한 정보 –
Dominik Brodowski <linux@brodo.de>
2. 리눅스 커널 안의 가버너들
3. CPUfreq 코어 안의 가버너 인터페이스
1. CPUFreq 가버너가 뭔가요?
대부분의 cpufreq 드라이버들(사실, longrun 하나를 빼고 모두다) 또는 대
CPUFreq 정책 안에서 무슨 주파수가 사용되어져야 하는 지는 어떻게 결정할
기본적으로, 다음 흐름도를 따릅니다:
CPU는 기정된 “제한사항”안에서 독립적으 | CPU는 지정 주파수로만
“CPUfreq 정책”
2. 리눅스 커널 안의 가버너들
2.1 성능(Performance)
CPUfreq 가버너 “performance”는 CPU를 정적으로 scaling_min_freq 와
CPUfreq 가버너 “powersave”는 CPU를 정적으로 scaling_min_freq 와
CPUfreq 가버너 “userspace”는 사용자에게, 또는 UID “root”로 실행되는
CPUfreq 가버너 “ondemand” 는 현재 사용량에 따라 CPU를 셋팅합니다.
sampling_rate: uS(10^-6 초)로 측정됨, 이것은 얼마나 자주 여러분이 커널이
sampling_rate_min:
up_threshold: 주파수를 증가시키는 게 좋을지에 대한 결정을 커널이 내리는데
ignore_nice_load: 이 파라미터는 ‘0’ 또는 ‘1’ 을 값으로 가집니다.
sampling_down_factor: 이 파라미터는 커널이 최고 속도에서 실행 중인 동안
“ondemand”와 매우 비슷한, CPUfreq 가버너 “conservation” 는 현재 사용량에
freq_step: 이것은 CPU 주파수가 그에 의해 부드럽게 중가되거나 감소되어야
down_threshold: “ondemand” 가버너에서 찾을 수 있는 ‘up_threshold’ 와 같지만,
2.6 상호적(Interactive)
CPUfreq 가버너 “interactive”는 지연 시간에 민감한 상호적 작업 부하에
이 가버너를 위해 맞출 수 있는 값들은 다음과 같습니다:
target_loads: CPU 부하 값은 현재 CPU 부하를 그 값으로 맞추기 위해서
85 1000000:90 1700000:99
hispeed_freq: gp_hispeed_load 로 지정된 값에 CPU 부하가 도달했을 때
go_hispeed_load: hispeed_freq 로 올라가는 CPU 부하. 기본은 99%.
above_hispeed_delay: 속도가 hispeed_freq 혹은 그 이상일 때, 계속되는
80000 1300000:200000 1500000:40000
CPU 속도 1.3 GHz 까지는 80000 uS 대기 시간이 사용되고, 1.5 GHz
timer_rate: CPU가 대기 상태가 아닐 때 CPU 부하를 재평가하기 위한
timer_slack: 최하 속도 이상의 속도로 실행 중일 때, timer_rate를 넘어
boost: 0이 아니면, 즉시 모든 CPU들의 속도를 이 속성에 0이 쓰여질 때까지
boostpulse: 쓰여질 때마다, 즉시 모든 CPU들의 속도를 적어도
boostpulse_duration: boostpulse에 쓰여질 때 보통의 부하에 따라 속도를
새로운 가버너는 그 자신을 CPUfreq 코어에 “cpufreq_register_governor”를
governor->name – 이 가버너의 유일한 이름
governor->governor 콜백은 그 CPU를 위한 현재의(또는 셋팅될)
CPUFREQ_GOV_START: 이 가버너가 그 CPU policy->cpu를 위해 그 의무를
여러분이 여러분의 드라이버의 다른 “이벤트들”을 외부적으로 필요로 한다면,
int cpufreq_driver_target(struct cpufreq_policy *policy,
int __cpufreq_driver_target(struct cpufreq_policy *policy,
target_freq 는 물론, policy->min과 policy->max 안에 있어야만 합니다.
[Linux:Kernel] Linux CPUFreq Core
이 문서의 저작권은 GPL License를 따릅니다(This document is released under the GPL license).
클럭 조정은 동작하고 있는 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와 함께 호출됩니다.
[Android:Build] Macro 정리
http://blog.naver.com/hyunsung1026/80145257300 에 정리가 잘 되어 있네요~ ^^
[git] git status 의 Untracked files 지우기
이거도 가끔 하는데 할 때 마다 긁자!
rm -rf `git status | grep -P “^#\t” | awk ‘{ print $2 }’`
[Linux] vmlinux -> Image
명령어만 덜렁 써놓기 뭐해서 설명을 덧붙인다.
가끔 undefined instrunction 예외가 날 때, 코드 메모리의 이상 여부를 확인해야 할 때가 있다.
커널은 알다시피 zImage를 Decompressed 하여 메모리상에 올린 후 실행하는데, 그 Decompressed Image가 Image 이다. Image는 커널의 빌드 과정에서 아래와 같이 objcopy를 이용해서 만든다. Makefile 을 참고해보면 알 수 있을 것이다. ARM의 경우는 arch/arm/boot/ 와 그 아래의 Makefile을 살펴보면 된다.
Android JB MR1의 경우 아래 경로의 prebuilt 된 툴체인을 사용한다.
나온 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 introduction 와 GPIO in the kernel: future directions 를 보고 나름의 정리를 해둔다.
1. 현재 GPIO의 Kernel Internal API
GPIO를 가지고 뭔가 하기 위해서 다음 헤더 파일을 include 한다.
현재의 커널은 모든 GPIO를 unsigned integer로 나타낸다. 그래서 platform data나 device tree를 통해 GPIO 번호를 넘기는 것이 가능하다.
GPIO는 사용 전에 allocation 되어야 한다. 현재 구현은 이를 강제하고 있지는 않다. allocation 은 다음 함수를 이용한다.
label은 나중에 sysfs 로 나타날 수 있다. 반환값 0은 성공, 다른 값은 음수로 에러 번호를 반환한다. 다음을 통해 GPIO를 다시 돌려줄 수 있다.
몇 가지 변형이 있는데 gpio_request_one() 은 초기 설정을 같이 할 수 있고, gpio_request_array() 는 몇 개의 GPIO를 한번에 설정하면서 request 할 수 있다. “managed” 버전(예를 들면, devm_gpio_request())은 개발자가 잊어버렸을 때 cleanup을 자동적으로 처리한단다(managed 버전이 있는 건 몰랐네…).
GPIO가 입력으로 사용되면,
출력으로 사용되면,
output 일 때 value는 꼭 0 이나 1로 지정되어야 한다. 둘 다 성공 시에는 0을, 아니면 음수로 에러 번호를 반환한다.
GPIO 입력값을 읽을 때는,
에러가 발생하려면 gpio_direction_input()을 호출했을 때 에러가 발생한다고 생각하기 때문에 별도 에러 체크는 하지 않는다. 그러므로 gpio_direction_input()의 반환값을 꼭 체크해야 한다.
GPIO 출력값을 설정할 때는 gpio_direction_output()을 사용할 수도 있지만, 이미 출력모드로 되어 있으면, 다음을 사용하는게 더 낫다.
몇몇 GPIO 컨트롤러는 GPIO 입력 값이 바뀌면 인터럽트를 걸어주는데, 이 IRQ 번호를 얻고 싶으면,
여기서의 gpio는 gpio_request() 로 꼭 얻어야 하고, gpio는 일단 입력 모드로 된다. irq 번호 대신 음수로 된 에러 번호가 반환될 수 있다. 반환된 irq는 request_irq()로 인터럽트 핸들러를 셋팅할 수 있다.
GPIO를 sysfs로 export 해서 user space에서 제어할 수 있도록 하려면,
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와 매우 비슷하다.
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를 얻을 수도 있다.
반대인 desc_to_gpio() 도 있다. desc로 gpio 번호를 얻으면 포인터에서 얻어진 것이므로 현재의 기존 GPIO API에 안심하고 쓸 수 있다. 그러나 GPIO 번호로 descriptor를 얻는 건 별로 좋지 않다. 그래서 다음을 제공한다.
dev는 GPIO 라인을 제공하는 device여야 하고, “name”은 라인을 말한다.
GPIO 라인 접근을 제거하기 위해서 gpiod_put() 도 제공한다.
3. Block GPIO
위에 설명한 것들은 개별 GPIO 라인을 관리하는데 초점을 둔다. 근데 GPIO들은 그룹으로 함께 쓰일 때가 많다.
어떤 하드웨어들은 또 한번의 I/O 메모리 write 연산으로 여러 라인을 동시에 바꿀 수 있다. 그래서 여러 GPIO를 하나의 그룹처럼 조작할 때, 하나의 블록으로 엮어서 사용하기 위해 Block GPIO 패치가 시도되었다. Descriptor-based GPIO API 에 비하면 별로 크게 다루어지지는 않았다.
gpios는 하나의 블록으로 그룹지어지는, GPIO 번호들의 size 크기의 Array 이다. name은 user spcae에서 그 블록으로 동작하는데 사용될 수 있다. gpios 안의 GPIO 들은 gpio_request()로 이전에 이미 요청되어져 있어야 하고, 그 direction 도 각각 셋팅되어져 있어야 한다. GPIO 들이 흩어져 있거나, 드라이버가 Internal Block APIO를 구현하지 않으면, 그냥 지금처럼 개별 라인으로 접근한다.
GPIO 블록의 조작은,
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 볼록은 다음으로 제거 가능하다.
User space에서 sysfs 로 GPIO 블록을 셋팅하거나 읽을 수 있도록하는, 등록 함수도 있다.
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 디텍터
번역 : 양정석(dasomoli@gmailREMOVETHIS.com)
===============================================================