ARM10C 82주차 후기
일시 : 2014.12.13 (82주차)
모임명 : NAVER개발자커뮤니티지원_IAMROOT.ORG_10차ARM-C
장소 : 토즈 타워점
장소지원 : NAVER 개발자 커뮤니티 지원 프로그램
참여인원 : 2명
82주차 진도
- start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree() *
main.c::start_kernel()
asmlinkage void __init start_kernel(void)
{
...
setup_arch(&command_line);
...
mm_init();
// buddy와 slab 을 활성화 하고 기존 할당 받은 bootmem 은 buddy,
// pcpu 메모리, vmlist 는 slab으로 이관
...
rcu_init();
// rcu 자료구조 bh, sched, preempt 를 각각 초기화 수행함
...
/* init some links before init_ISA_irqs() */
early_irq_init();
// irq_desc 0 ~ 15 까지의 object을 할당 받고 초기화를 수행
// allocated_irqs에 bit를 1로 세팅하고 radix tree에 각 irq_desc를 노트로 추가
init_IRQ();
- call: start_kernel()->init_IRQ()
irq.c::init_IRQ()
- called: start_kernel()->init_IRQ()
// ARM10C 20141004
void __init init_IRQ(void)
{
// CONFIG_OF=y, machine_desc->init_irq: __mach_desc_EXYNOS5_DT.init_irq: 0
if (IS_ENABLED(CONFIG_OF) && !machine_desc->init_irq)
irqchip_init();
else
machine_desc->init_irq();
}
- call: start_kernel()->init_IRQ()->irqchip_init()
irqchip.h::irqchip_init()
- called: start_kernel()->init_IRQ()->irqchip_init()
// ARM10C 20141004
extern struct of_device_id __irqchip_begin[];
// ARM10C 20141004
void __init irqchip_init(void)
{
// exynos-combiner.c 에 정의된 함수를 사용하여 초기화 수행
// __irqchip_begin: irqchip_of_match_exynos4210_combiner
of_irq_init(__irqchip_begin);
}
#ifdef CONFIG_IRQCHIP // CONFIG_IRQCHIP=y
#define IRQCHIP_OF_MATCH_TABLE() \
. = ALIGN(8); \
VMLINUX_SYMBOL(__irqchip_begin) = .; \
*(__irqchip_of_table) \
*(__irqchip_of_end)
#else
#define IRQCHIP_OF_MATCH_TABLE()
#endif
- call: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()
- // exynos-combiner.c 에 정의된 함수를 사용하여 초기화 수행
- // __irqchip_begin: irqchip_of_match_exynos4210_combiner
- of_irq_init(__irqchip_begin);
irqchip.h::irqchip_init()
- called: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()
- // exynos-combiner.c 에 정의된 함수를 사용하여 초기화 수행
- // __irqchip_begin: irqchip_of_match_exynos4210_combiner
- of_irq_init(__irqchip_begin);
void __init of_irq_init(const struct of_device_id *matches)
{
struct device_node *np, *parent = NULL;
// parent: NULL
struct intc_desc *desc, *temp_desc;
struct list_head intc_desc_list, intc_parent_list;
INIT_LIST_HEAD(&intc_desc_list);
// intc_desc_list 리스트 초기화 수행
INIT_LIST_HEAD(&intc_parent_list);
// intc_parent_list 리스트 초기화 수행
// matches: irqchip_of_match_exynos4210_combiner
for_each_matching_node(np, matches) {
// for (np = of_find_matching_node(NULL, matches); np; np = of_find_matching_node(np, matches))
// np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
// of_find_property(devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소, "interrupt-controller", NULL):
// combiner node의 "interrupt-controller" property의 주소
// np: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
// of_find_property(devtree에서 allnext로 순회 하면서 찾은 gic node의 주소, "interrupt-controller", NULL):
// gic node의 "interrupt-controller" property의 주소
if (!of_find_property(np, "interrupt-controller", NULL))
continue;
/*
* Here, we allocate and populate an intc_desc with the node
* pointer, interrupt-parent device_node etc.
*/
// sizeof(struct intc_desc): 16 bytes, GFP_KERNEL: 0xD0
// kzalloc(16, GFP_KERNEL: 0xD0): kmem_cache#30-o10
// sizeof(struct intc_desc): 16 bytes, GFP_KERNEL: 0xD0
// kzalloc(16, GFP_KERNEL: 0xD0): kmem_cache#30-o11
desc = kzalloc(sizeof(*desc), GFP_KERNEL);
// desc: kmem_cache#30-o10
// desc: kmem_cache#30-o11
// desc: kmem_cache#30-o10
// desc: kmem_cache#30-o11
if (WARN_ON(!desc))
goto err;
// desc->dev: (kmem_cache#30-o10)->dev, np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
// desc->dev: (kmem_cache#30-o11)->dev, np: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
desc->dev = np;
// desc->dev: (kmem_cache#30-o10)->dev: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
// desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
// desc->interrupt_parent: (kmem_cache#30-o10)->interrupt_parent, np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
// of_irq_find_parent(devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소): gic node 주소
// desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent, np: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
// of_irq_find_parent(devtree에서 allnext로 순회 하면서 찾은 gic node의 주소): gic node 주소
desc->interrupt_parent = of_irq_find_parent(np);
// desc->interrupt_parent: (kmem_cache#30-o10)->interrupt_parent: gic node 주소
// desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: gic node 주소
// desc->interrupt_parent: (kmem_cache#30-o10)->interrupt_parent: gic node 주소
// np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
// desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: gic node 주소
// np: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
if (desc->interrupt_parent == np)
// desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: gic node 주소
desc->interrupt_parent = NULL;
// desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: NULL
// &desc->list: &(kmem_cache#30-o10)->list
// &desc->list: &(kmem_cache#30-o11)->list
list_add_tail(&desc->list, &intc_desc_list);
// intc_desc_list에 (kmem_cache#30-o10)->list를 tail에 추가
// intc_desc_list에 (kmem_cache#30-o11)->list를 tail에 추가
}
// irqchip_of_match_exynos4210_combiner, irqchip_of_match_cortex_a15_gic 의
// struct intc_desc 메모리 할당, intc_desc 맴버가 초기화 된 값이 intc_desc_list list의 tail로 추가됨
// list_empty(&intc_desc_list): 0
while (!list_empty(&intc_desc_list)) {
list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
// for (desc = list_first_entry(&intc_desc_list, typeof(*desc), list),
// temp_desc = list_next_entry(desc, list);
// &desc->list != (&intc_desc_list);
// desc = temp_desc, temp_desc = list_next_entry(temp_desc, list))
// desc: kmem_cache#30-o10 (exynos4210_combiner), temp_desc: kmem_cache#30-o11 (cortex_a15_gic)
// desc: kmem_cache#30-o11 (cortex_a15_gic), temp_desc: NULL
const struct of_device_id *match;
int ret;
of_irq_init_cb_t irq_init_cb;
// desc->interrupt_parent: (kmem_cache#30-o10)->interrupt_parent: gic node 주소, parent: NULL
// desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: NULL, parent: NULL
if (desc->interrupt_parent != parent)
continue;
// continue 수행 (exynos4210_combiner)
// &desc->list: (kmem_cache#30-o11)->list
list_del(&desc->list);
// intc_desc_list에서 (kmem_cache#30-o11)->list를 삭제
// matches: irqchip_of_match_cortex_a15_gic,
// desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
// of_match_node(cortex_a15_gic, devtree에서 allnext로 순회 하면서 찾은 gic node의 주소):
// irqchip_of_match_cortex_a15_gic
match = of_match_node(matches, desc->dev);
// match: irqchip_of_match_cortex_a15_gic
// match->data; irqchip_of_match_cortex_a15_gic.data: gic_of_init
if (WARN(!match->data,
"of_irq_init: no init function for %s\n",
match->compatible)) {
kfree(desc);
continue;
}
// match->compatible: irqchip_of_match_cortex_a15_gic.compatible: "arm,cortex-a15-gic",
// desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
// desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: NULL
pr_debug("of_irq_init: init %s @ %p, parent %p\n",
match->compatible,
desc->dev, desc->interrupt_parent);
// "of_irq_init: init arm,cortex-a15-gic @ 0x(gic node의 주소), parent 0\n"
// match->data; irqchip_of_match_cortex_a15_gic.data: gic_of_init
irq_init_cb = (of_irq_init_cb_t)match->data;
// irq_init_cb: gic_of_init
// desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소,
// desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: NULL
// gic_of_init(devtree에서 allnext로 순회 하면서 찾은 gic node의 주소, NULL):
ret = irq_init_cb(desc->dev, desc->interrupt_parent);
// ret: 0
if (ret) {
kfree(desc);
continue;
}
/*
* This one is now set up; add it to the parent list so
* its children can get processed in a subsequent pass.
*/
// &desc->list: &(kmem_cache#30-o11)->list
list_add_tail(&desc->list, &intc_parent_list);
// intc_parent_list에 tail로 &(kmem_cache#30-o11)->list를 추가
}
// &desc->list: &intc_desc_list 이므로 loop 탈출
/* Get the next pending parent that might have children */
// typeof(*desc): struct intc_desc
// list_first_entry_or_null(&intc_parent_list, struct intc_desc, list):
// (!list_empty(&intc_parent_list) ? list_first_entry(&intc_parent_list, struct intc_desc, list) : NULL)
// list_first_entry(&intc_parent_list, struct intc_desc, list): kmem_cache#30-o11 (cortex_a15_gic)
desc = list_first_entry_or_null(&intc_parent_list,
typeof(*desc), list);
// desc: kmem_cache#30-o11 (cortex_a15_gic)
// desc: kmem_cache#30-o11 (cortex_a15_gic)
if (!desc) {
pr_err("of_irq_init: children remain, but no parents\n");
break;
}
// &desc->list: &(kmem_cache#30-o11 (cortex_a15_gic))->list
list_del(&desc->list);
// &(kmem_cache#30-o11 (cortex_a15_gic))->list에 연결된 list 삭제
// parent: NULL
// desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
parent = desc->dev;
// parent: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
// desc: kmem_cache#30-o11 (cortex_a15_gic)
kfree(desc);
log
43b267c..fc76100 master -> origin/master
Updating 43b267c..fc76100
Fast-forward
arch/arm/include/asm/bitops.h | 4 +
arch/arm/include/asm/hw_irq.h | 2 +
arch/arm/kernel/irq.c | 22 ++-
arch/arm/lib/findbit.S | 4 +
drivers/irqchip/exynos-combiner.c | 129 ++++++++++++++-
drivers/irqchip/irq-gic.c | 113 +++++++------
drivers/of/base.c | 1 +
drivers/of/irq.c | 184 ++++++++++++++++++++-
include/linux/irq.h | 27 ++++
include/linux/irqdomain.h | 1 +
include/linux/list.h | 5 +
include/linux/of.h | 10 ++
include/linux/of_irq.h | 7 +-
include/linux/types.h | 1 +
include/uapi/asm-generic/errno-base.h | 2 +
kernel/irq/chip.c | 85 +++++++++-
kernel/irq/internals.h | 10 ++
kernel/irq/irqdesc.c | 293 ++++++++++++++++++++++------------
kernel/irq/irqdomain.c | 246 ++++++++++++++++++++++++++--
lib/bitmap.c | 32 ++++
20 files changed, 1003 insertions(+), 175 deletions(-)
fc76100..0ba901e master -> origin/master
Updating fc76100..0ba901e
Fast-forward
drivers/irqchip/exynos-combiner.c | 110 +++++++++++++++++++++++++++----------
kernel/irq/irqdesc.c | 112 +++++++++++++++++++++++++++-----------
kernel/irq/irqdomain.c | 112 +++++++++++++++++++++++++++-----------
3 files changed, 242 insertions(+), 92 deletions(-)
댓글 없음:
댓글 쓰기