# IRQ를 기록할 소프트웨어 객체부터 만듭니다

v6.18.37 / kernel/irq/irqdesc.c

인터럽트 컨트롤러를 설정하기 전에 Linux가 IRQ 번호별 상태를 보관할 자료구조가 필요합니다. irq_desc가 그 관리 객체입니다. 이 예제는 CONFIG_SPARSE_IRQ 쪽 정의를 읽으며, 모든 구성에서 같은 저장 방식이라고 가정하지 않습니다.

## early_irq_init

```c

int __init early_irq_init(void)
{
	int i, initcnt, node = first_online_node;
	struct irq_desc *desc;

	init_irq_default_affinity();

	/* Let arch update nr_irqs and return the nr of preallocated irqs */
	initcnt = arch_probe_nr_irqs();
	printk(KERN_INFO "NR_IRQS: %d, nr_irqs: %d, preallocated irqs: %d\n",
	       NR_IRQS, nr_irqs, initcnt);

	if (WARN_ON(nr_irqs > MAX_SPARSE_IRQS))
		nr_irqs = MAX_SPARSE_IRQS;

	if (WARN_ON(initcnt > MAX_SPARSE_IRQS))
		initcnt = MAX_SPARSE_IRQS;

	if (initcnt > nr_irqs)
		nr_irqs = initcnt;

	for (i = 0; i < initcnt; i++) {
		desc = alloc_desc(i, node, 0, NULL, NULL);
		irq_insert_desc(i, desc);
	}
	return arch_early_irq_init();
}

```

### 549행

```c

int __init early_irq_init(void)

```

IRQ 번호에 대응하는 irq_desc 소프트웨어 관리 객체와 기본 CPU 배치를 마련합니다. 하드웨어 컨트롤러 초기화 전에 준비하는 단계이며 마지막 아키텍처 초기화 결과를 반환합니다.

### 551행

```c

	int i, initcnt, node = first_online_node;

```

i는 초기 IRQ 번호 순회에, initcnt는 미리 만들 관리 객체 수에 사용합니다. node는 그 객체 메모리를 할당할 첫 온라인 NUMA 노드입니다.

### 552행

```c

	struct irq_desc *desc;

```

현재 번호에 대해 만든 IRQ 관리 객체를 담습니다. 이 객체는 핸들러·상태·잠금 등을 관리하며 인터럽트 컨트롤러의 하드웨어 레지스터 자체가 아닙니다. 포인터가 보관하는 것은 객체의 주소입니다. 이 선언만으로 대상 구조체나 문자열의 내용이 복사되지는 않습니다.

### 554행

```c

	init_irq_default_affinity();

```

별도 정책이 없을 때 IRQ가 실행될 CPU 집합의 기본값을 준비합니다.

### 557행

```c

	initcnt = arch_probe_nr_irqs();

```

아키텍처가 요구하는 초기 IRQ 개수를 얻습니다.

### 558행

```c

	printk(KERN_INFO "NR_IRQS: %d, nr_irqs: %d, preallocated irqs: %d\n",

```

IRQ 번호 공간의 빌드 기준값, 현재 관리 범위와 미리 만들 객체 수를 비교해 출력합니다. 이 셋이 항상 같은 값일 필요는 없습니다.

### 559행

```c

	       NR_IRQS, nr_irqs, initcnt);

```

앞 로그에 각각 빌드 기준, 런타임 IRQ 범위와 사전 할당 개수를 넘깁니다. 뒤에서는 Sparse IRQ 상한과 비교해 지나치게 큰 값을 제한합니다. 앞줄에서 시작한 호출이나 식에 이어지는 부분이므로, 이 줄만으로 별도의 함수 호출이 생기지는 않습니다.

### 561행

```c

	if (WARN_ON(nr_irqs > MAX_SPARSE_IRQS))

```

필요한 IRQ 번호 범위가 Sparse IRQ 구현의 상한을 넘는지 검사합니다. 참이면 경고하고 아래에서 nr_irqs를 지원 가능한 상한으로 낮춥니다.

### 562행

```c

		nr_irqs = MAX_SPARSE_IRQS;

```

관리할 IRQ 수를 Sparse IRQ 구현이 지원하는 상한으로 제한합니다.

### 564행

```c

	if (WARN_ON(initcnt > MAX_SPARSE_IRQS))

```

미리 만들 irq_desc 수가 구현 상한을 넘는지 확인합니다. 경고만 내는 것이 아니라 아래 대입으로 실제 반복 범위도 제한합니다.

### 565행

```c

		initcnt = MAX_SPARSE_IRQS;

```

미리 만들 IRQ 객체 수도 구현의 상한을 넘지 않게 줄입니다.

### 567행

```c

	if (initcnt > nr_irqs)

```

미리 만들어야 할 IRQ 객체 수가 현재 IRQ 번호 범위보다 큰지 확인합니다.

### 568행

```c

		nr_irqs = initcnt;

```

초기 객체들을 모두 표현할 수 있게 관리할 IRQ 번호 수를 늘립니다.

### 570행

```c

	for (i = 0; i < initcnt; i++) {

```

초기에 사용할 0번부터 initcnt-1번까지 각 IRQ에 대해 관리 객체를 만들고 번호 조회 구조에 등록합니다. 실제 장치 IRQ를 발생시키는 반복이 아닙니다.

### 571행

```c

		desc = alloc_desc(i, node, 0, NULL, NULL);

```

IRQ 번호와 노드 정보에 맞춰 irq_desc 관리 객체를 만듭니다.

### 572행

```c

		irq_insert_desc(i, desc);

```

생성한 IRQ 객체를 번호로 찾을 수 있는 관리 구조에 넣습니다.

### 574행

```c

	return arch_early_irq_init();

```

범용 자료구조 준비 뒤 아키텍처의 이른 IRQ 초기화 결과를 돌려줍니다.

