도메인 기관 이전 완료

기존에 잘 사용하던 호스트웨이(www.hostway.co.kr)가 처음 쓸 때는 6900원이었다가 16000원쯤으로 올랐는데 귀찮아서 계속 쓰다가 오늘 호스팅케이알(hostring.kr) 로 기관 이전 신청했다. 사실 hostway 쓸 때 아이디를 그 쪽에서 그냥 만들었는지, 내가 평소에 쓰는 아이디가 아니라서 매번 로그인할 때마다 찾아야 했던 것도 불편하고..

하면서 알게 된 사실은 도메인 lock을 unlock 하더라도 propagation 하는데 시간이 좀 걸린다는 거. 어제 Unlock 하고 오늘 했더니 된다.

hostway 에서 인증 코드 얻는 것도 웹 상에서 얻을 수 있도록 잘 되어 있네~

DNS 설정도 바꿔야 하나, 하고 좀 귀찮은게 꺼려지지만, 그래도 일년에 커피 한잔 정도를 나에게 더 쓸 수 있겠다.

[Linux:Kernel] 지연시간 – 다양한 커널 딜레이(delay) / 슬립(sleep) 메카니즘의 정보

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

Documentation/timers/timers-howto.txt

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

지연시간 – 다양한 커널 딜레이(delay) / 슬립(sleep) 메카니즘의 정보

——————————————————————
이 문서는 공통적인 질문에 대해 답변하려고 합니다: “무엇이 지연 시간을
추가하는 옳은 방법(RightWay (TM)) 인가?”
이 질문은 하드웨어 지연 시간을 처리해야만 하지만, 커널의 내부
동작과는 거의 직접적으로 관련이 없을 드라이버 작성자들에 의해서
거의 제기됩니다.
딜레이 추가하기
—————
먼저, 가장 중요한, 여러분에게 물을 필요가 있는 질문은 “내 코드가
어토믹 컨텍스트(atomic context) 안에 있는가?” 입니다. 이것은 “정말로
어토믹 컨텍스트 안의 딜레이가 필요한가”라는 질문이 따라 붙어야 합니다.
만약 그렇다면…
어토믹 컨텍스트:
여러분은 *delay 계열의 함수를 사용해야만 합니다. 이들 함수는
클럭 속도의 지피(jiffie) 추정하기를 사용하고, 원하는 지연
시간을 채우기 위해서 충분한 루프 사이클을 바쁘게 대기(busy
wait)할 것입니다:
ndelay(unsigned long nsecs)
udelay(unsigned long usecs)
mdelay(unsigned long msecs)
udelay 는 일반적으로 선호되는 API 입니다; ndelay-레벨
정밀도는 많은 PC가 아닌(non-PC) 기기들에서 실제로 존재하지
않을 것입니다.
mdelay 는 udelay에 큰 인자를 주었을 때 가능한 오버 플로우
(overflow)를 세는, 돌고 도는 udelay의 매크로입니다.
일반적으로, mdelay의 사용은 권장되지 않고, 코드는 msleep를
사용할 수 있도록 리팩토링되는 것이 좋습니다.
어토믹이 아닌(NON-ATOMIC) 컨텍스트:
여러분은 *sleep[_range] 계열의 함수를 사용하는 것이 좋습니다.
여기에 몇가지 더 많은 옵션이 있습니다. 여기 있는 어떤 것들도
정확히 동작할 것이긴 하지만, “알맞은” 슬립 함수를 사용하는 것은
스케줄러와 전력 관리를 돕고, 여러분의 드라이버를 더 좋게
만들어줄 것입니다. 🙂
— 바쁜 대기(busy-wait)루프로 뒷받침:
udelay(unsigned long usecs)
— hrtimers로 뒷받침:
usleep_range(unsigned long min, unsigned long max)
— 지피 / 기존 타이머(legacy timer)로 뒷받침:
msleep(unsigned long msecs)
msleep_interruptible(unsigned long msecs)
*dealy 계열과 다르게, 이들 각각의 호출을 수행하는 바닥에 깔린
메카니즘이 다양하기 때문에 여러분이 알고 있어야 할 특성이 있습니다.
적은 USECS ( < ~10us? ) 를 위한 슬립:
* udelay를 사용하세요.
– usleep은 왜 아닌가요?
느린 시스템에서, (임베디드, 또는 아마도 스피드-스텝
PC!) usleep 을 위해서 hrtimers를 셋팅하는 오버헤드
(overhead)가 *아마* 그만큼 가치가 없을 것입니다. 앞과
같은 측정은 명확히 여러분의 재원적 사항에 달려 있습니다만,
알아둘 만 한 것은 아닙니다.
~USECS 나 작은 MSECS ( 10us – 20ms ) 를 위한 슬립:
* usleep_range를 사용하세요.
– (1ms – 20ms)를 위한 msleep은 왜 아닌가요?
원래는 여기서 설명했습니다:
http://lkml.org/lkml/2007/8/3/250
msleep(1~20) 은 호출자가 의도한 것을 하지 않을 수 있고,
종종 더 길게(1~20ms 사이의 어떤 값에 대해서도 실제
~20 ms 슬립) 슬립할 것입니다. 많은 경우에 이것은 원하는
동작이 아닙니다.
– “usleep” 은 왜 없나요 / 좋은 범위는 무엇인가요?
usleep_range 는 hrtimers의 꼭대기에서 빌드되므로, 그
웨이크업(wakeup)은 매우 정밀할 것입니다. 그래서 간단한
usleep 함수는 거의 많은 수의 원치 않는 인터럽트를 일으킵니다.
범위의 도입으로, 스케줄러는 여러분의 웨이크업을 다른 이유로
인해 일어날 수 있는, 혹은, 최악의 경우에 여러분의
상한(upper bound)을 위한 인터럽트를 점화하는 다른
웨이크업과 합치는데 자유롭게 됩니다.
여러분이 범위를 더 넓게 할 수록, 여러분이 인터럽트를
일으키지 않을 기회가 더 커집니다; 이것은 여러분의 코드
경로에서 지연 시간/성능 상의 허락할만한 상한값과
균형을 맞추어야 합니다. 여기에서 정확한 허용값은 매우 상황에
의존적입니다. 그래서 이는 호출자에게 이유가 있는 범위를
결정하도록 남겨둡니다.
더 큰 MSEC ( 10ms+ ) 를 위한 슬립
* msleep 이나 가능하면 msleep_interruptible 을 사용하세요.
– 무슨 차이인가요?
msleep 은 현재 태스크를 TASK_UNINTERRUPTIBLE 로 셋팅하는데
반해, msleep_interruptible 은 현재 태스크를 그 슬립을
스케줄링하기 전에 TASK_INTERRUPTIBLE 로 셋팅합니다.
요약하면, 차이는 슬립이 시그널에 의해 일찍 끝날 수 있는지
입니다. 일반적으로, 여러분이 인터럽트 가능한 파생 형태가
필요하다는 것을 알기 전까지는 그냥 msleep을 사용하세요.

[Android] ${ro.hardware}를 사용한 하드웨어 별 init.rc 처리

안 적어 놓으니 역시나 까먹는다. 아래는 ARM 32비트에 국한한다.

커널 부팅의 마지막에 init 프로세스가 시작되면, 램디스크 안에 든 init.rc 파일을 읽어 처리하게 된다. 별 다른 처리를 하지 않았다면, 기본적으로 system/core/rootdir/init.rc 파일이 램디스크로 복사되므로 이 파일을 읽어 처리한다.
이 init.rc 파일에서는 ro.hardware 프로퍼티 값에 따라 init.${ro.hardware}.rc 파일을 읽어 처리하게 되는데 이 파일로 각 보드마다 다른 처리를 가능하게 한다.
여기서 ro.hardware 프로퍼티 값은 init(system/core/init) 안에서 다음과 같은 순서로 셋팅한다.

1. /proc/cpuinfo 를 읽어서 이 안의 “Hardware:” 뒤의 값을 소문자로 모두 바꿔 사용(system/core/init/util.c 의 get_hardware_name())
2. 부트로더에서 cmdline 으로 androidboot.hardware 값이 넘어왔다면, ro.boot.hardware 프로퍼티로 셋팅한다(system/core/init/init.c 의 import_kernel_nv()).[ro.boot.hardware 값은 꼭 부트로더에서 넘어오지 않을 수도 있다]
3. ro.boot.hardware 프로퍼티 값이 있다면, 앞에서 /proc/cpuinfo 에서 읽은 값을 오버라이드한다.

위의 순서를 거쳐 셋팅된 ro.hardware 프로퍼티를 사용해서 init.${ro.hardware}.rc 파일을 읽게 된다.

1. 의 경우를 사용할 때는 /proc/cpuinfo 값을 사용하므로, 리눅스 커널의 사용되는 struct machine_desc 안의 .name 을 사용하게 된다.
/proc/cpuinfo 에서 “Hardware: ” 를 출력하는 부분은 리눅스 커널 소스의 arch/arm/kernel/setup.c 안의 c_show() 함수를 보면 되는데, 다음과 같다.

static int c_show(struct seq_file *m, void *v)
{
        …

        seq_printf(m, “Hardware\t: %s\n”, machine_name);

        …

machine_name 은 커널 부팅 중 (arch/arm/kernel/setup.c 의) setup_arch() 에서 다음처럼 셋팅한다.

void __init setup_arch(char **cmdline_p)
{

        …
        machine_name = mdesc->name;

        …

struct machine_desc 안의 .name 은 대부분 머신 파일 안에서 MACHINE_START(_type, _name) 매크로를 통해 선언한다. _name이 .name이 된다. 그러므로 결국 _name 에 들어가는 값이 읽혀 소문자로 바뀌어 사용된다. 예를 들면, Nexus 10 디바이스의 경우 다음과 같이 arch/arm/mach-exynos/board-manta.c 안에 다음과 같이 정의되어 있다. 여기서는 “Manta” 가 소문자로 모두 바뀌어 manta 로 사용된다.

MACHINE_START(MANTA, “Manta”)
        … 
MACHINE_END


참고로, MACHINE_START 매크로는 arch/arm/include/asm/mach/arch.h 에 있는데 다음과 같다.

#define MACHINE_START(_type,_name)                      \
static const struct machine_desc __mach_desc_##_type    \
 __used                                                 \
 __attribute__((__section__(“.arch.info.init”))) = {    \
        .nr             = MACH_TYPE_##_type,            \
        .name           = _name,
#define MACHINE_END                             \
};

2. 의 경우는 cmdline 을 통해 넘어오므로, 부트로더에서 ATAG를 통해 cmdline 에 셋팅하여 넘기는 것이 가장 정상적인 방법이고, 편법으로는 cmdline 을 바꿀 수 있는 여러가지 방법(예를 들면, 커널 컴파일 타임에 셋팅한다든지, boot.img 를 만들 때 cmdline 을 설정해 준다든지 등)을 통해 셋팅할 수 있다.(아니면 아예 ro.boot.hardware 값을 직접 셋팅해도 아마?)
androidboot.hardware 값이 ro.boot.hardware 프로퍼티 값이 되는 과정은 system/core/init/init.c 의 import_kernel_nv() 함수 내에서 처리된다.

static void import_kernel_nv(char *name, int for_emulator)
{                          
    …
    if (!strcmp(name,”qemu”)) {
        strlcpy(qemu, value, sizeof(qemu));
    } else if (!strncmp(name, “androidboot.”, 12) && name_len > 12) {
        const char *boot_prop_name = name + 12;
        char prop[PROP_NAME_MAX];
        int cnt;
        
        cnt = snprintf(prop, sizeof(prop), “ro.boot.%s”, boot_prop_name);
        if (cnt < PROP_NAME_MAX)
            property_set(prop, value);
    }
}

3. 의 ro.boot.hardware 프로퍼티 값이 ro.hardware 프로퍼티 값으로 셋팅되는 과정은 system/core/init/init.c 의 export_kernel_boot_props() 에서 수행된다. 이 과정 중에 ro.boot.hardware 프로퍼티 값이 있다면, 1. 의 /proc/cpuinfo 을 통해 얻은 값을 오버라이드하게 된다.

static void export_kernel_boot_props(void)
{
    … 
    /* if this was given on kernel command line, override what we read
     * before (e.g. from /proc/cpuinfo), if anything */
    ret = property_get(“ro.boot.hardware”, tmp);
    if (ret)
        strlcpy(hardware, tmp, sizeof(hardware));

    property_set(“ro.hardware”, hardware);  

[Linux:Kernel] 원형 버퍼(Circular Buffer)

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

      =========
      원형 버퍼
      =========
작성: David Howells <dhowells@redhat.com>
      Paul E. McKenney <paulmck@linux.vnet.ibm.com>
번역: 양정석 <dasomoli@gmailREMOVETHIS.com>
리눅스는 원형 버퍼를 구현하는데 사용할 수 있는 많은 기능을 제공합니다.
다음의 두가지 셋이 있습니다:
 (1) 2의 거듭제곱 크기의 버퍼에 대한 정보를 결정하기 위한 편리한 함수들
 (2) 버퍼 안의 객체의 생산자와 소비자가 하나의 락(lock)을 공유하지 않기를
     원할 때를 위한 메모리 장벽
이들 기능을 사용하기 위해서, 아래에서 논의되는 것처럼, 적어도 하나의 생산자와
하나의 소비자가 있어야 합니다. 여러 생산자를 처리하는 것도 그들을 연속적으로
일렬로 늘어놓는 것으로, 여러 소비자를 처리하는 것도 그들을 연속적으로 일렬로
늘어놓는 것으로써 처리 가능합니다.
내용:
 (*) 원형 버퍼가 뭔가요?
 
 (*) 2의 거듭제곱 버퍼 측정.
 (*) 원형 버퍼와 함께 메모리 장벽 사용하기
     – 생산자.
     – 소비자.
===================
원형 버퍼가 뭔가요?
===================
가장 먼저, 원형 버퍼가 뭘까요? 원형 버퍼는 그 안에 두가지 인덱스가 있는 유한한
크기의 고정된 버퍼입니다:
 (1) ‘헤드(head)’ 인덱스 – 생산자가 항목을 버퍼로 집어넣는 곳
 (2) ‘테일(tail)’ 인덱스 – 소비자가 다음 항목을 버퍼에서 찾는 곳
일반적으로 테일 포인터가 헤드 포인터와 같을 때, 그 버퍼는 빈 것입니다; 그리고 그
버퍼는 헤드 포인터가 테일 포인터보다 하나 작을 때, 가득 찬 것입니다. 
헤드 인덱스는 아이템들이 추가될 때, 테일 인덱스는 아이템들이 제거될 때 증가합니다.
테일 인덱스는 헤드 인덱스를 절대로 넘어설 수 없고, 두 인덱스 모두 그들이 버퍼의
끝에 다다랐을 때, 0으로 다시 돌아와야 합니다. 그래서 무한한 양의 데이터가
그 버퍼를 통해 흐를 수 있습니다.
일반적으로 항목들은 모두 같은 단위 크기이지만, 아래 테크닉을 사용하는 것이
엄격하게 요구되지는 않습니다. 인덱스들은 여러 항목이나 가변 크기의 항목들이
두 인덱스 모두 다른 것을 추월하지 않도록 제공되는 그 버퍼 안으로 포함된다면,
1보다 더 많이 증가할 수 있습니다. 그러나 그 구현자는 한 단위 크기 이상의
한 부분은 버퍼의 끝을 돌 수 있고, 두 세그먼트로 쪼개질 수 있기 때문에 조심해야
합니다.
=======================
2의 거듭제곱 버퍼 측정
=======================
제멋대로인 크기의 원형 버퍼의 사용하거나 남아있는 양의 계산은 보통 나머지
(나누기) 명령의 사용을 필요로 하는 느린 동작이 됩니다. 그러나 버퍼가 2의
거듭제곱 크기라면, 훨씬 빠른 비트-앤드(bitwise-AND) 명령을 대신 사용할 수
있습니다.
리눅스는 2의 거듭 제곱 원형 버퍼를 처리하기 위한 매크로 셋을 제공합니다. 이들은
다음을 통해 사용할 수 있습니다:
#include <linux/circ_buf.h>
그 매크로들은:
  (*) 버퍼의 남은 양 측정:
CIRC_SPACE(head_index, tail_index, buffer_size);
     이것은 항목들이 넣어질 수 있는 그 버퍼[1] 안에 남은 공간의 양을 반환합니다.
 (*) 버퍼 안에 최대로 연이어 붙어있는 공간 측정:
CIRC_SPACE_TO_END(head_index, tail_index, buffer_size);
     이것은 항목들이 다시 그 버퍼의 처음으로 돌아가는 것 없이 즉시 삽입되어질
     수 있는 그 버퍼[1] 안에 남은 연이은 공간의 양을 반환합니다.
 (*) 버퍼의 사용량 측정:
CIRC_CNT(head_index, tail_index, buffer_size);
     이것은 현재 버퍼[2]를 사용하는 항목 수를 반환합니다
 (*) 처음으로 돌아가는 것이 없을 때(non-wrapping)의 버퍼 사용량 측정:
CIRC_CNT_TO_END(head_index, tail_index, buffer_size);
     이것은 다시 그 버퍼의 처음으로 돌아가는 것 없이 뽑아 낼 수 있는 연이은
     항목들[2]의 수를 반환합니다.
이들 매크로 각각은 명목상으로 0 에서 buffer_size-1 사이의 값을 반환할 것입니다.
그러나:
 [1] CIRC_SPACE*() 들은 생산자 안에서 사용되도록 의도되었습니다. 생산자에게
     그들은 생산자가 헤드 인덱스를 제어하기 때문에 하한값을 반환할 것입니다.
     그러나 소비자는 여전히 다른 CPU 상에서 그 버퍼를 감소시키고, 테일 인덱스를
     옮기고 있을 수 있습니다.
     생산자가 그 공간을 바쁘게 감소시킬 수 있기 때문에, 소비자에게 그것은
     상한값을 보여줄 것입니다.
 [2] CIRC_CNT*() 들은 소비자 안에서 사용되도록 의도되었습니다. 소비자에게
     그들은 소비자가 테일 인덱스를 제어하기 때문에 하한값을 반환할 것입니다.
     그러나 생산자는 여전히 다른 CPU 상에서 그 버퍼를 채우고, 헤드 인덱스를
     옮기고 있을 수 있습니다.
     소비자가 그 버퍼를 바쁘게 비울 수 있기 때문에, 생산자에게 그것은 상한값을
     보여줄 것입니다.
 [3] 서드 파티에게는, 생산자와 소비자가 보여질 수 있게 되어감에 의해, 그
     인덱스들에 쓰는 순서는 그들이 독립적이고, 다른 CPU 상에서 생성될 있기 때문에
     보장될 수 없습니다. 그래서 이런 상황에서의 결과는 그저 추정이 될 것이고, 아예
     틀릴 수도 있습니다.
=======================================
원형 버퍼와 함께 메모리 장벽 사용하기
=======================================
원형 버퍼와 함께 메모리 장벽을 사용함으로써, 여러분은 다음을 위한 욕구를
피할 수 있습니다.
 (1) 그 버퍼의 양 끝으로의 접근을 다스리기 위한 단일 락(lock) 사용, 그래서
     그 버퍼가 동시에 채우고 비울 수 있는; 그리고
 (2) 어토믹(atomic) 카운터 연산 사용
이를 위한 두 편이 있습니다: 그 버퍼를 채우는 생산자, 그를 비우는 소비자.
어느 한번에 하나만 버퍼를 채워야 하고, 어느 한번에 하나만 버퍼를 비워야 합니다만,
두 편은 동시에 수행할 수 있습니다.
생산자
——
생산자는 이처럼 보일 것입니다:
spin_lock(&producer_lock);
unsigned long head = buffer->head;
unsigned long tail = ACCESS_ONCE(buffer->tail);
if (CIRC_SPACE(head, tail, buffer->size) >= 1) {
/* 버퍼로 아이템 하나를 넣어라 */
struct item *item = buffer[head];
produce_item(item);
smp_wmb(); /* 헤드를 증가시키기 전에 항목을 넣어라 */
buffer->head = (head + 1) & (buffer->size – 1);
/* wake_up() 은 어느 하나가 깨기 전에 헤드가 제출됐음을 확인할
* 것이다 */
wake_up(consumer);
}
spin_unlock(&producer_lock);
이는 CPU가 새로운 항목의 내용을 헤드 인덱스가 소비자에게 사용가능하게 만들기
전에 반드시 쓰여져야 한다는 것을 지시할 것이고, 그 후 그 CPU가 소비자가 깨기
전에 바뀐 헤드 인덱스가 쓰여져야만 함을 지시합니다.
wake_up() 이 꼭 사용하는 그 메카니즘일 필요는 없지만, 만약 상태 변경이 일어난다면,
사용되는 아무 것이나 헤드 인덱스의 갱신과 소비자의 상태 변경 사이에 반드시 한번의
(쓰기) 메모리 장벽을 보장해야 함을 명심하세요.
소비자
——
소비자는 이처럼 보일 것입니다:
spin_lock(&consumer_lock);
unsigned long head = ACCESS_ONCE(buffer->head);
unsigned long tail = buffer->tail;
if (CIRC_CNT(head, tail, buffer->size) >= 1) {
/* 그 인덱스에 있는 내용을 읽기 전에 인덱스를 읽어라 */
smp_read_barrier_depends();
/* 버퍼로부터 하나의 항목을 꺼내라 */
struct item *item = buffer[tail];
consume_item(item);
smp_mb(); /* 테일을 증가시키기 전에 서술자 읽기를 끝내라 */
buffer->tail = (tail + 1) & (buffer->size – 1);
}
spin_unlock(&consumer_lock);
이는 CPU가 새로운 항목을 읽기 전에 그 인덱스가 올라갔음을 확인할 것을 지시할
것이고, 그 후 CPU가 그 항목을 지울 새로운 테일 포인터를 쓰기 전에 그 항목
읽기를 끝냈음을 확인하도록 합니다.
반대 인덱스를 읽기 위한 두 알고리듬 안에 ACCESS_ONCE() 의 사용에 주의하세요.
이것은 컴파일러가 그들의 캐시된 값-어떤 컴파일러는 smp_read_barrier_depends()를
가로질러 수행하는-을 버리고 재로딩하는 것을 막습니다. 여러분이 반대 인덱스가
한 번만 사용될 거라고 알 수 있다면, 이것이 엄격히 필요하지는 않습니다.
=============
더 읽을 거리
=============
리눅스의 메모리 장벽 기능에 대한 설명을 위해 Documentation/memory-barriers.txt도
보세요.

[Linux:Kernel] 어떻게 I2C 디바이스를 인스턴스로 만드는가(How to instantiate I2C devices)

이 문서의 라이센스는 GPL 을 따릅니다(This document is released under the GPL license).

Documentation/i2c/instantiating-devices

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

어떻게 I2C 디바이스를 인스턴스로 만드는가

=========================================
PCI나 USB 디바이스와 다르게, I2C 디바이스들은 하드웨어 레벨에서 열겨되지
않습니다. 대신에, 소프트웨어가 어떤 디바이스가 각 I2C 버스 세그먼트에
붙어 있는지, 어떤 주소를 이 디바이스가 사용하는지 알아야만 합니다. 이런
이유로, 커널 코드는 I2C 디바이스들을 명시적으로 인스턴스로 만듭니다.
컨텍스트와 요구 사항에 따라 이렇게 할 수 있는 여러 방법이 있습니다.
방법 1: I2C 디바이스를 버스 번호로 선언하기
——————————————-
이 방법은 많은 임베디드 시스템을 위한 경우처럼, I2C 버스가 하나의 시스템
버스일 때, 적절합니다. 이런 시스템 상에서, 각 I2C 버스는 미리 알려진
번호를 가집니다. 그래서 이 버스 상에서 활동하는 I2C 디바이스를 미리 선언
(pre-declare)하는 것이 가능합니다. 이것은 i2c_register_board_info() 를
호출함으로써 등록되는 struct i2c_board_info 의 배열로 수행됩니다.
예제(omap2 h4):
static struct i2c_board_info h4_i2c_board_info[] __initdata = {
{
I2C_BOARD_INFO(“isp1301_omap”, 0x2d),
.irq = OMAP_GPIO_IRQ(125),
},
{ /* EEPROM on mainboard */
I2C_BOARD_INFO(“24c01”, 0x52),
.platform_data = &m24c01,
},
{ /* EEPROM on cpu card */
I2C_BOARD_INFO(“24c01”, 0x57),
.platform_data = &m24c01,
},
};
static void __init omap_h4_init(void)
{
(…)
i2c_register_board_info(1, h4_i2c_board_info,
ARRAY_SIZE(h4_i2c_board_info));
(…)
}
위의 코드는 I2C 버스 1 상에 그들 각각의 주소와 그들 드라이버가 필요로 하는
각각에 맞는 데이터를 포함하는 3개의 디바이스를 선언합니다. 해당 I2C 버스가
등록될 때, I2C 디바이스들은 i2c-core에 의해 자동으로 인스턴스로 될 것입니다.
디바이스들은 그들이 장착된 I2C 버스가 (만약) 없어진다면 자동으로 해제되고
소멸됩니다.
방법 2: 디바이스를 명시적으로 인스턴스로 만들기
———————————————–
이 방법은 좀 더 큰 디바이스가 I2C 버스를 내부 통신 용으로 사용할 때
적절합니다. 일반적인 경우는 TV 어댑터입니다. 이들은 보통 I2C 버스로 메인
칩에 연결되는 튜너, 비디오 디코더, 오디오 디코더, 기타 등을 가질 수
있습니다. 여러분은 미리 I2C 버스의 개수를 알 수 없을텐데, 그래서 위에서
설명한 방법 1 은 사용할 수 없습니다. 대신에 여러분은 여러분의 I2C 디바이스를
명시적으로 인스턴스로 만들 수 있습니다. 이것은 struct i2c_board_info 를
채우고, i2c_new_device() 를 호출함으로써 수행합니다.
예제 (sfe4001 네트워크 드라이버):
static struct i2c_board_info sfe4001_hwmon_info = {
I2C_BOARD_INFO(“max6647”, 0x4e),
};
int sfe4001_init(struct efx_nic *efx)
{
(…)
efx->board_info.hwmon_client =
i2c_new_device(&efx->i2c_adap, &sfe4001_hwmon_info);
(…)
}
위의 코드는 진행 중에 네트워크 어댑터의 I2C 버스 상의 1개의 I2C 디바이스를
인스턴스로 만듭니다.
다른 경우는 I2C 디바이스가 있는지 없는지를 모를 때, 혹은 한 보드로부터
(제조자가 공지없이 그 디자인을 바꾼) 다음 보드로 다른 주소를 가질 때 입니다.
이 경우, 여러분은 i2c_new_device() 대신 i2c_new_probed_device()를 호출할
수 있습니다.
예제 (nxp OHCI 드라이버):
static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
static int usb_hcd_nxp_probe(struct platform_device *pdev)
{
(…)
struct i2c_adapter *i2c_adap;
struct i2c_board_info i2c_info;
(…)
i2c_adap = i2c_get_adapter(2);
memset(&i2c_info, 0, sizeof(struct i2c_board_info));
strlcpy(i2c_info.type, “isp1301_nxp”, I2C_NAME_SIZE);
isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,
  normal_i2c, NULL);
i2c_put_adapter(i2c_adap);
(…)
}
위의 코드는 진행 중에 OHCI 어댑터에 있는 I2C 버스 상에 1개의 I2C 디바이스를
인스턴스로 만듭니다. 그것은 먼저 0x2c 주소로 시도하고 아무것도 찾지 못하면,
0x2d 주소로 시도하고 나서도 여전히 아무 것도 찾지 못하면, 간단히 포기합니다.
I2C 디바이스를 인스턴스로 만드는 드라이버가 소멸을 위한 청소 작업을
책임집니다. 이는 i2c_new_device() 나 i2c_new_probed_device() 에 의해
반환됐던 포인터 상의 i2c_unregister_device() 를 호출함으로써 수행됩니다.
방법 3: 특정 디바이스를 위한 I2C 버스 감지하기
———————————————-
i2c_new_probed_device() 를 호출한다 할지라도, 어떤 때, 여러분은 I2C
디바이스에 대한 충분한 정보를 갖고 있지 못합니다. 일반적인 경우는 PC 메인보드
상의 하드웨어 모니터링 칩입니다. 25 개의 다른 주소로 장착될 수 있는 많은
모델이 있습니다. 거기다 어마어마한 숫자의 메인보드가 있어, 사용되는 하드웨어
모니터링 칩의 하나도 빠뜨리지 않은 철저한 리스트를 빌드하는 것은 불가능합니다.
운좋게도 이들 대부분의 칩은 제조사와 디바이스 ID 레지스터를 가지기 때문에,
그들은 감지(probing)에 의해서 식별될 수 있습니다.
이런 경우, I2C 디바이스들은 명시적으로 선언되지 않거나, 인스턴스로 되지
않습니다. 대신에, 이런 디바이스를 위한 i2c-core 는 그 드라이버가 로드되자
마자, 어떤 것이 찾아지면, 감지할 것이고, I2C 디바이스는 자동으로 인스턴스로
만들어질 것입니다. 이 메카니즘의 어떠한 오동작도 막기 위해서, 다음 제약 사항이
적용됩니다:
* I2C 디바이스 드라이버는 임의의 레지스터를 읽음으로써 지원되는 디바이스를
  식별할 수 있는 detect() 메소드를 구현해야만 합니다.
* 오직 지원하는 디바이스를 가질 듯하고, 감지를 허용하는 버스들만 감지될
  것입니다. 예를 들면 이것은 TV 어댑터 상의 하드웨어 모니터링 칩을 위한 감지는
  피합니다.
  
예제:
drivers/hwmon/lm90.c 안의 lm90_driver 와 lm90_detect() 를 보세요.
성공적인 감지의 결과로서 인스턴스로 만들어진 I2C 디바이스는 그들을 감지했던
드라이버가 제거될 때, 혹은 아래 깔려있는 I2C 버스 그 스스로가 소멸될 때,
어느 것이 먼저 일어나든지, 자동으로 소멸될 것입니다.
2.4 커널의 i2c 서브 시스템과 초기 2.6 커널에 익숙한 여러분들은 이 방법 3 이
이전에 했던 방법과 기본적으로 비슷한 것을 알 수 있을 것입니다. 두 가지 명확한
차이가 있습니다:
* 감지하는 것은 그 당시에는 I2C 디바이스를 인스턴스로 만드는 유일한 방법이었던
  데 반해, 지금은 그저 하나의 방법일 뿐입니다. 가능한 곳에서는 방법 1 과 2 가
  더 우선되어야 합니다. 방법 3 은 원치 않는 부작용이 있을 수 있기 때문에 다른
  방법이 없을 때에만 사용되어야 합니다.
* 그 당시에는 모든 I2C 버스가 기본값으로 감지되었었던데 반해, I2C 버스들은
  지금은 명시적으로 어떤 I2C 드라이버 클래스가 (그 클래스 비트 필드를 이용해서)
  그들을 감지할 수 있는지 알려줘야만 합니다. 기본값은 아무 감지도 하지 않음을
  의미하는 텅빈 클래스입니다. 그 클래스 비트 필드의 목적은 앞서 언급했던 원치
  않는 부작용을 제한하기 위함입니다.
  
다시 한번, 방법 3은 가능한 곳에서 피하는 것이 좋습니다. 명시적인 디바이스
인스턴스로 만들기(방법 1 과 2)가 더 안전하고, 더 빠른, 훨씬 좋은 방법입니다.
방법 4: 유저-스페이스(user-space)에서 인스턴스로 만들기
——————————————————-
일반적으로, 커널은 어떤 I2C 디바이스가 연결되었고, 어떤 주소를 그들이
사용하는지 알아야만 합니다. 그러나 특정 경우에는 그렇지 않기 때문에
사용자들이 그 정보를 제공하게 하도록 sysfs 인터페이스가 추가되었습니다.
이 인터페이스는 모든 I2C 버스 디렉토리 안에 생성되는 2개의 속성 파일을
생성합니다: new_device 와 delete_device, 두 파일 모두 쓰기 전용이고,
여러분은 그들에 적절하게 I2C 디바이스를 인스턴스를 만들고, 각각 삭제하도록
옳은 파라미터를 써야만 합니다.
new_device 파일은 2 파라미터를 가집니다: 그 I2C 디바이스의 이름(문자열)과
그 I2C 디바이스의 주소(숫자, 일반적으로 0x로 시작하는 16진수, 그러나
10진수로도 표현 가능함)
delete_device 파일은 하나의 파라미터를 가집니다: 그 I2C 디바이스의 주소.
두 디바이스가 주어진 I2C 세그먼트 상에 같은 주소로 장착될 수 없듯이,
그 주소는 삭제하기 위한 디바이스를 유일하게 식별할 수 있는 충분조건입니다.
예제:
# echo eeprom 0x50 > /sys/bus/i2c/devices/i2c-3/new_device
이 인터페이스는 커낼 내부(in-kernel) 디바이스 선언이 수행될 수 없을 때에만
사용되어져야 하지만, 유용할 수 있는 여러 경우가 있습니다:
* I2C 드라이버가 일반적으로 디바이스를 감지하지만(방법 3) 여러분의 디바이스가
  장착된 그 버스 세그먼트는 더 적절한 클래스 비트 셋을 가지지 않고, 그래서
  감지가 되지 않을 때.
* I2C 드라이버가 일반적으로 디바이스를 감지하지만, 여러분의 디바이스가 알 수 없는
  주소에 장착될 때.
* I2C 드라이버가 일반적으로 디바이스를 감지하지만, 감지 루틴이 너무 엄격하거나,
  여러분의 디바이스가 공식적으로 아직 지원되지 않기 때문에 여러분의 디바이스가
  감지되지 않지만 여러분은 그와 호환되는 것을 알 때.
* I2C 디바이스를 여러분 스스로 납땜해서 테스트 보드 상에서 드라이버를 개발
  중일 때.
  
이 인터페이스는 몇몇 I2C 드라이버가 구현한 force_* 모듈 파라미터를 대체합니다.
i2c-core 안에 구현된 것이 각 디바이스 드라이버 각자가 구현한 것보다는
훨신 더 효율적이고, 또한 여러분이 셋팅을 바꾸기 위한 드라이버를 다시 로드하지
않아도 된다는 이점을 가집니다. 여러분은 또한 드라이버가 로드되기 전이나 이용
가능하기 전에조차 디바이스를 인스턴스로 만들 수 있고, 그 디바이스가
무슨 드라이버를 필요로 하는지 알 필요도 없습니다.

[WinMerge] Linux Kernel 디렉토리 비교를 위한 Filter

커널은 빌드하면 .cmd 같은게 나와서 디렉토리로 비교하면 저런거 때문에 더럽다.

그래서 필터에 .cmd 같은거 추가해서 쓰면 된다~

다음을 Linux.flt 같은걸로 저장해서 필터 있는데다 같이 넣어주자~

## This is a directory/file filter template for WinMerge
name: Linux
desc: for Linux kernel
## Select if filter is inclusive or exclusive
## Inclusive (loose) filter lets through all items not matching rules
## Exclusive filter lets through only items that match to rule
## include or exclude
def: include
## Filters for filenames begin with f:
## Filters for directories begin with d:
## (Inline comments begin with ” ##” and extend to the end of the line)
f: \.o$
f: \.lib$
f: \.bak$ ## backup
f: \.cmd$
d: \\cvs$ ## CVS control directory