============
-
tick_nohz_init()
-
null funtion
-
context_tracking_init()
-
null function
-
radix_tree_init()
-
radix tree로 사용하는 radix_tree_node_cachep에 kmem_cache#20을 생성 및 초기화 후 할당하고
-
height_to_maxindex을 초기화 수행
-
early_irq_init();
-
irq_desc 0 ~ 15 까지의 object을 할당 받고 초기화를 수행
-
allocated_irqs에 bit를 1로 세팅하고 radix tree에 각 irq_desc를 노트로 추가
-
init_IRQ();
-
exynos-combiner.c 에 정의된 함수를 사용하여 초기화 수행
-
__irqchip_begin: irqchip_of_match_exynos4210_combiner
asmlinkage void __init start_kernel(void)
{
...
boot_cpu_init();
// 현재 cpu(core id)를 얻어서 cpu_XXX_bits[] 의 cpu를 셋한다.
...
setup_arch(&command_line);
...
mm_init();
// buddy와 slab 을 활성화 하고 기존 할당 받은 bootmem 은 buddy,
// pcpu 메모리, vmlist 는 slab으로 이관
sched_init();
// scheduler가 사용하는 자료 구조 초기화, idle_threads를 init_task로 세팅
preempt_disable();
// preempt count를 증가시켜 preemption 못하도록 막음
...
rcu_init();
// rcu 자료구조 bh, sched, preempt 를 각각 초기화 수행함
tick_nohz_init(); // null function
context_tracking_init(); // null function
radix_tree_init();
// radix tree로 사용하는 radix_tree_node_cachep에 kmem_cache#20을 생성 및 초기화 후 할당하고
// height_to_maxindex을 초기화 수행
/* init some links before init_ISA_irqs() */
early_irq_init();
// irq_desc 0 ~ 15 까지의 object을 할당 받고 초기화를 수행
// allocated_irqs에 bit를 1로 세팅하고 radix tree에 각 irq_desc를 노트로 추가- Null Function
// ARM10C 20141004
static inline void tick_nohz_init(void) { }- Null Function
// ARM10C 20141004
static inline void context_tracking_init(void) { }// ARM10C 20141004
// #define RADIX_TREE_INIT(GFP_KERNEL):
// {
// .height = 0,
// .gfp_mask = (GFP_KERNEL),
// .rnode = NULL,
// }
#define RADIX_TREE_INIT(mask) { \
.height = 0, \
.gfp_mask = (mask), \
.rnode = NULL, \
}// ARM10C 20141004
int __init early_irq_init(void)
{
// first_online_node: 0
int i, initcnt, node = first_online_node;
// node: 0
struct irq_desc *desc;
init_irq_default_affinity();
// init_irq_default_affinity에서 한일:
// irq_default_affinity->bits[0]: 0xF
/* Let arch update nr_irqs and return the nr of preallocated irqs */
// arch_probe_nr_irqs(): 16
initcnt = arch_probe_nr_irqs();
// initcnt: 16
// NR_IRQS: 16, nr_irqs: 16, initcnt: 16
printk(KERN_INFO "NR_IRQS:%d nr_irqs:%d %d\n", NR_IRQS, nr_irqs, initcnt);
// "NR_IRQS:16 nr_irqs:16 16"
// nr_irqs: 16, IRQ_BITMAP_BITS: 8212
if (WARN_ON(nr_irqs > IRQ_BITMAP_BITS))
nr_irqs = IRQ_BITMAP_BITS;
// initcnt: 16, IRQ_BITMAP_BITS: 8212
if (WARN_ON(initcnt > IRQ_BITMAP_BITS))
initcnt = IRQ_BITMAP_BITS;
// initcnt: 16, nr_irqs: 16
if (initcnt > nr_irqs)
nr_irqs = initcnt;
// initcnt: 16
for (i = 0; i < initcnt; i++) {
// i: 0, node: 0
// alloc_desc(0, 0, NULL): kmem_cache#28-o0
desc = alloc_desc(i, node, NULL);
// desc: kmem_cache#28-o0
// i: 0
set_bit(i, allocated_irqs);
// allocated_irqs[0]: 0x1
// i: 0, desc: kmem_cache#28-o0
irq_insert_desc(i, desc);
// radix tree에 kmem_cache#28-o0를 노드로 추가
// i: 1 ... 15 수행
}
// arch_early_irq_init(): 0
return arch_early_irq_init();
// return 0
}- initcnt: 16
// ARM10C 20141004
// &irq_default_affinity, GFP_NOWAIT: 0
static inline bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags)
{
return true;
}// ARM10C 20141004
// irq_default_affinity
static inline void cpumask_setall(struct cpumask *dstp)
{
// dstp: irq_default_affinity, cpumask_bits(irq_default_affinity): irq_default_affinity->bits,
// nr_cpumask_bits: 4
bitmap_fill(cpumask_bits(dstp), nr_cpumask_bits);
// irq_default_affinity->bits[0]: 0xF
}// ARM10C 20141004
// irq_default_affinity->bits, nr_cpumask_bits: 4
static inline void bitmap_fill(unsigned long *dst, int nbits)
{
// nbits: 4, BITS_TO_LONGS(4): 1
size_t nlongs = BITS_TO_LONGS(nbits);
// nlongs: 1
// nbits: 4, small_const_nbits(4): 1
if (!small_const_nbits(nbits)) {
int len = (nlongs - 1) * sizeof(unsigned long);
memset(dst, 0xff, len);
}
// dst: irq_default_affinity->bits, nlongs: 1, nbits: 4, BITMAP_LAST_WORD_MASK(4): 0xF
dst[nlongs - 1] = BITMAP_LAST_WORD_MASK(nbits);
// irq_default_affinity->bits[0]: 0xF
}- irq_default_affinity->bits[0]: 0xF
- initcnt = arch_probe_nr_irqs();
- // arch_probe_nr_irqs(): 16
#ifdef CONFIG_SPARSE_IRQ // CONFIG_SPARSE_IRQ=y
int __init arch_probe_nr_irqs(void)
{
// machine_desc->nr_irqs: __mach_desc_EXYNOS5_DT.nr_irqs: 0, NR_IRQS: 16
nr_irqs = machine_desc->nr_irqs ? machine_desc->nr_irqs : NR_IRQS;
// nr_irqs: 16
// nr_irqs: 16
return nr_irqs;
// return 16
}- irq_default_affinity->bits[0]: 0xF
#if defined(CONFIG_SMP) // CONFIG_SMP=y
// ARM10C 20141004
static void __init init_irq_default_affinity(void)
{
// GFP_NOWAIT: 0
// alloc_cpumask_var(&irq_default_affinity, 0): 0
alloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT);
cpumask_setall(irq_default_affinity);
// irq_default_affinity->bits[0]: 0xF
}
#else
static void __init init_irq_default_affinity(void)
{
}
#endif- initcnt: 16
for (i = 0; i < initcnt; i++) {
// i: 0, node: 0
// alloc_desc(0, 0, NULL): kmem_cache#28-o0
desc = alloc_desc(i, node, NULL);
// desc: kmem_cache#28-o0
// alloc_desc(0)에서 한일:
// (kmem_cache#28-o0)->kstat_irqs: pcp 4 byte 공간
// (kmem_cache#28-o0)->lock 을 이용한 spinlock 초기화 수행
// (kmem_cache#28-o0)->irq_data.irq: 0
// (kmem_cache#28-o0)->irq_data.chip: &no_irq_chip
// (kmem_cache#28-o0)->irq_data.chip_data: NULL
// (kmem_cache#28-o0)->irq_data.handler_data: NULL
// (kmem_cache#28-o0)->irq_data.msi_desc: NULL
// (kmem_cache#28-o0)->status_use_accessors: 0xc00
// (&(kmem_cache#28-o0)->irq_data)->state_use_accessors: 0x10000
// (kmem_cache#28-o0)->handle_irq: handle_bad_irq
// (kmem_cache#28-o0)->depth: 1
// (kmem_cache#28-o0)->irq_count: 0
// (kmem_cache#28-o0)->irqs_unhandled: 0
// (kmem_cache#28-o0)->name: NULL
// (kmem_cache#28-o0)->owner: null
// [pcp0...3] (kmem_cache#28-o0)->kstat_irqs: 0
// (kmem_cache#28-o0)->irq_data.node: 0
// (kmem_cache#28-o0)->irq_data.affinity.bits[0]: 0xF
// i: 0
set_bit(i, allocated_irqs);
// allocated_irqs[0]: 0x1
// i: 0, desc: kmem_cache#28-o0
irq_insert_desc(i, desc);
// radix tree에 kmem_cache#28-o0를 노드로 추가
// i: 1 ... 15 수행
}// ARM10C 20141004
// i: 0, node: 0, null
static struct irq_desc *alloc_desc(int irq, int node, struct module *owner)
{
struct irq_desc *desc;
// GFP_KERNEL: 0xD0
gfp_t gfp = GFP_KERNEL;
// gfp: GFP_KERNEL: 0xD0
// sizeof(struct irq_desc): 156 bytes, gfp: GFP_KERNEL: 0xD0, node: 0
// kzalloc_node(156, GFP_KERNEL: 0xD0, 0): kmem_cache#28-o0
desc = kzalloc_node(sizeof(*desc), gfp, node);
// desc: kmem_cache#28-o0
// desc: kmem_cache#28-o0
if (!desc)
return NULL;
/* allocate based on nr_cpu_ids */
// desc->kstat_irqs: (kmem_cache#28-o0)->kstat_irqs
// alloc_percpu(unsigned int): pcp 4 byte 공간 할당
desc->kstat_irqs = alloc_percpu(unsigned int);
// desc->kstat_irqs: (kmem_cache#28-o0)->kstat_irqs: pcp 4 byte 공간
// desc->kstat_irqs: (kmem_cache#28-o0)->kstat_irqs: pcp 4 byte 공간
if (!desc->kstat_irqs)
goto err_desc;
// desc: kmem_cache#28-o0, gfp: GFP_KERNEL: 0xD0, node: 0
// alloc_masks(kmem_cache#28-o0, GFP_KERNEL: 0xD0, 0): 0
if (alloc_masks(desc, gfp, node))
goto err_kstat;
// alloc_masks에서 한일:
// (kmem_cache#28-o0)->irq_data.affinity.bits[0]: 0
// desc->lock: (kmem_cache#28-o0)->lock
raw_spin_lock_init(&desc->lock);
// desc->lock: (kmem_cache#28-o0)->lock 을 이용한 spinlock 초기화 수행
// desc->lock: (kmem_cache#28-o0)->lock
lockdep_set_class(&desc->lock, &irq_desc_lock_class); // null function
// irq: 0, desc: kmem_cache#28-o0, node: 0, owner: null
desc_set_defaults(irq, desc, node, owner);
// desc_set_defaults에서 한일:
// (kmem_cache#28-o0)->irq_data.irq: 0
// (kmem_cache#28-o0)->irq_data.chip: &no_irq_chip
// (kmem_cache#28-o0)->irq_data.chip_data: NULL
// (kmem_cache#28-o0)->irq_data.handler_data: NULL
// (kmem_cache#28-o0)->irq_data.msi_desc: NULL
// (kmem_cache#28-o0)->status_use_accessors: 0xc00
// (&(kmem_cache#28-o0)->irq_data)->state_use_accessors: 0x10000
// (kmem_cache#28-o0)->handle_irq: handle_bad_irq
// (kmem_cache#28-o0)->depth: 1
// (kmem_cache#28-o0)->irq_count: 0
// (kmem_cache#28-o0)->irqs_unhandled: 0
// (kmem_cache#28-o0)->name: NULL
// (kmem_cache#28-o0)->owner: null
// [pcp0...3] (kmem_cache#28-o0)->kstat_irqs: 0
// (kmem_cache#28-o0)->irq_data.node: 0
// (kmem_cache#28-o0)->irq_data.affinity.bits[0]: 0xF
return desc;
err_kstat:
free_percpu(desc->kstat_irqs);
err_desc:
kfree(desc);
return NULL;
}// ARM10C 20141004
// sizeof(struct irq_desc): 156 bytes, gfp: GFP_KERNEL: 0xD0, node: 0
static inline void *kzalloc_node(size_t size, gfp_t flags, int node)
{
// size: 156, flags: GFP_KERNEL: 0xD0, __GFP_ZERO: 0x8000u, node: 0
// kmalloc_node(156, 0x80D0, 0): kmem_cache#28-o0
return kmalloc_node(size, flags | __GFP_ZERO, node);
// return kmem_cache#28-o0
}// ARM10C 20141004
// size: 156, flags: 0x80D0, node: 0
static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node)
{
#ifndef CONFIG_SLOB // CONFIG_SLOB=n
// size: 156, KMALLOC_MAX_CACHE_SIZE: 0x2000, flags: 0x80D0, GFP_DMA: 0x01u
if (__builtin_constant_p(size) &&
size <= KMALLOC_MAX_CACHE_SIZE && !(flags & GFP_DMA)) {
// size: 156, kmalloc_index(156): 2
int i = kmalloc_index(size);
// i: 2
// i: 2
if (!i)
return ZERO_SIZE_PTR;
// i: 2, kmalloc_caches[2]: kmem_cache#28, flags: 0x80D0, node: 0, size: 156
// kmem_cache_alloc_node_trace(kmem_cache#28, 0x80D0, 0, 156): kmem_cache#28-o0
return kmem_cache_alloc_node_trace(kmalloc_caches[i],
flags, node, size);
// return kmem_cache#28-o0
}
#endif
return __kmalloc_node(size, flags, node);
}// ARM10C 20141004
// size: 16
static __always_inline int kmalloc_index(size_t size)
{
// size: 16
if (!size)
return 0;
// size: 16, KMALLOC_MIN_SIZE: 64
if (size <= KMALLOC_MIN_SIZE)
// KMALLOC_SHIFT_LOW: 6
return KMALLOC_SHIFT_LOW;
// return 6
if (KMALLOC_MIN_SIZE <= 32 && size > 64 && size <= 96)
return 1;
if (KMALLOC_MIN_SIZE <= 64 && size > 128 && size <= 192)
return 2;
if (size <= 8) return 3;
if (size <= 16) return 4;
if (size <= 32) return 5;
if (size <= 64) return 6;
if (size <= 128) return 7;
if (size <= 256) return 8;
if (size <= 512) return 9;
if (size <= 1024) return 10;
if (size <= 2 * 1024) return 11;
if (size <= 4 * 1024) return 12;
if (size <= 8 * 1024) return 13;
if (size <= 16 * 1024) return 14;
if (size <= 32 * 1024) return 15;
if (size <= 64 * 1024) return 16;
if (size <= 128 * 1024) return 17;
if (size <= 256 * 1024) return 18;
if (size <= 512 * 1024) return 19;
if (size <= 1024 * 1024) return 20;
if (size <= 2 * 1024 * 1024) return 21;
if (size <= 4 * 1024 * 1024) return 22;
if (size <= 8 * 1024 * 1024) return 23;
if (size <= 16 * 1024 * 1024) return 24;
if (size <= 32 * 1024 * 1024) return 25;
if (size <= 64 * 1024 * 1024) return 26;
BUG();
/* Will never be reached. Needed because the compiler may complain */
return -1;
}// ARM10C 20141004
// unsigned int
#define alloc_percpu(type) \
(typeof(type) __percpu *)__alloc_percpu(sizeof(type), __alignof__(type))#ifdef CONFIG_SMP // CONFIG_SMP=y
// ARM10C 20141004
// desc: kmem_cache#28-o0, gfp: GFP_KERNEL: 0xD0, node: 0
static int alloc_masks(struct irq_desc *desc, gfp_t gfp, int node)
{
// desc->irq_data.affinity: &(kmem_cache#28-o0)->irq_data.affinity, gfp: GFP_KERNEL: 0xD0, node: 0
// zalloc_cpumask_var_node(&(kmem_cache#28-o0)->irq_data.affinity, GFP_KERNEL: 0xD0, 0): true
if (!zalloc_cpumask_var_node(&desc->irq_data.affinity, gfp, node))
return -ENOMEM;
// (kmem_cache#28-o0)->irq_data.affinity.bits[0]: 0
#ifdef CONFIG_GENERIC_PENDING_IRQ // CONFIG_GENERIC_PENDING_IRQ=n
if (!zalloc_cpumask_var_node(&desc->pending_mask, gfp, node)) {
free_cpumask_var(desc->irq_data.affinity);
return -ENOMEM;
}
#endif
return 0;
}// ARM10C 20141004
// &desc->irq_data.affinity: &(kmem_cache#28-o0)->irq_data.affinity, gfp: GFP_KERNEL: 0xD0, node: 0
static inline bool zalloc_cpumask_var_node(cpumask_var_t *mask, gfp_t flags,
int node)
{
// *mask: (kmem_cache#28-o0)->irq_data.affinity
cpumask_clear(*mask);
// (kmem_cache#28-o0)->irq_data.affinity.bits[0]: 0
return true;
}// ARM10C 20141004
// *mask: (kmem_cache#28-o0)->irq_data.affinity
static inline void cpumask_clear(struct cpumask *dstp)
{
// dstp: (kmem_cache#28-o0)->irq_data.affinity, nr_cpumask_bits: 4
bitmap_zero(cpumask_bits(dstp), nr_cpumask_bits);
// (kmem_cache#28-o0)->irq_data.affinity.bits[0]: 0
}// ARM10C 20141004
// dstp: (kmem_cache#28-o0)->irq_data.affinity, nr_cpumask_bits: 4
static inline void bitmap_zero(unsigned long *dst, int nbits)
{
if (small_const_nbits(nbits))
*dst = 0UL;
else {
int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
memset(dst, 0, len);
}
}// ARM10C 20140830
// &rt_b->rt_runtime_lock: &(&def_rt_bandwidth)->rt_runtime_lock
# define raw_spin_lock_init(lock) \
do { \
static struct lock_class_key __key; /* struct lock_class_key { }; */ \
\
__raw_spin_lock_init((lock), #lock, &__key); \
} while (0)
#else
# define raw_spin_lock_init(lock) \
do { *(lock) = __RAW_SPIN_LOCK_UNLOCKED(lock); } while (0)
#endif# define lockdep_set_class_and_name(lock, key, name) \
do { (void)(key); (void)(name); } while (0)// ARM10C 20141004
// irq: 0, desc: kmem_cache#28-o0, node: 0, owner: null
static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node,
struct module *owner)
{
int cpu;
// desc->irq_data.irq: (kmem_cache#28-o0)->irq_data.irq, irq: 0
desc->irq_data.irq = irq;
// desc->irq_data.irq: (kmem_cache#28-o0)->irq_data.irq: 0
// desc->irq_data.chip: (kmem_cache#28-o0)->irq_data.chip
desc->irq_data.chip = &no_irq_chip;
// desc->irq_data.chip: (kmem_cache#28-o0)->irq_data.chip: &no_irq_chip
// desc->irq_data.chip_data: (kmem_cache#28-o0)->irq_data.chip_data
desc->irq_data.chip_data = NULL;
// desc->irq_data.chip_data: (kmem_cache#28-o0)->irq_data.chip_data: NULL
// desc->irq_data.handler_data: (kmem_cache#28-o0)->irq_data.handler_data
desc->irq_data.handler_data = NULL;
// desc->irq_data.handler_data: (kmem_cache#28-o0)->irq_data.handler_data: NULL
// desc->irq_data.msi_desc: (kmem_cache#28-o0)->irq_data.msi_desc
desc->irq_data.msi_desc = NULL;
// desc->irq_data.msi_desc: (kmem_cache#28-o0)->irq_data.msi_desc: NULL
// desc: kmem_cache#28-o0, 0xFFFFFFFF, _IRQ_DEFAULT_INIT_FLAGS: 0xc00
irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS);
// irq_settings_clr_and_set에서 한일:
// desc->status_use_accessors: (kmem_cache#28-o0)->status_use_accessors: 0xc00
// &desc->irq_data: &(kmem_cache#28-o0)->irq_data, IRQD_IRQ_DISABLED: 0x10000
irqd_set(&desc->irq_data, IRQD_IRQ_DISABLED);
// irqd_set에서 한일:
// d->state_use_accessors: (&(kmem_cache#28-o0)->irq_data)->state_use_accessors: 0x10000
// desc->handle_irq: (kmem_cache#28-o0)->handle_irq
desc->handle_irq = handle_bad_irq;
// desc->handle_irq: (kmem_cache#28-o0)->handle_irq: handle_bad_irq
// desc->depth: (kmem_cache#28-o0)->depth
desc->depth = 1;
// desc->depth: (kmem_cache#28-o0)->depth: 1
// desc->irq_count: (kmem_cache#28-o0)->irq_count
desc->irq_count = 0;
// desc->irq_count: (kmem_cache#28-o0)->irq_count: 0
// desc->irqs_unhandled: (kmem_cache#28-o0)->irqs_unhandled
desc->irqs_unhandled = 0;
// desc->irqs_unhandled: (kmem_cache#28-o0)->irqs_unhandled: 0
// desc->name: (kmem_cache#28-o0)->name
desc->name = NULL;
// desc->name: (kmem_cache#28-o0)->name: NULL
// desc->owner: (kmem_cache#28-o0)->owner, owner: null
desc->owner = owner;
// desc->owner: (kmem_cache#28-o0)->owner: null
for_each_possible_cpu(cpu)
// for ((cpu) = -1; (cpu) = cpumask_next((cpu), (cpu_possible_mask)), (cpu) < nr_cpu_ids; )
// desc->kstat_irqs: (kmem_cache#28-o0)->kstat_irqs, cpu: 0
*per_cpu_ptr(desc->kstat_irqs, cpu) = 0;
// [pcp0] (kmem_cache#28-o0)->kstat_irqs: 0
// cpu: 1 .. 3 수행
// desc: kmem_cache#28-o0, node: 0
desc_smp_init(desc, node);
// desc_smp_init에서 한일:
// desc->irq_data.node: (kmem_cache#28-o0)->irq_data.node: 0
// desc->irq_data.affinity: (kmem_cache#28-o0)->irq_data.affinity.bits[0]: 0xF
}- desc->irq_data.node: (kmem_cache#28-o0)->irq_data.node: 0
- desc->irq_data.affinity: (kmem_cache#28-o0)->irq_data.affinity.bits[0]: 0xF
// ARM10C 20141004
// desc: kmem_cache#28-o0, node: 0
static void desc_smp_init(struct irq_desc *desc, int node)
{
// desc->irq_data.node: (kmem_cache#28-o0)->irq_data.node, node: 0
desc->irq_data.node = node;
// desc->irq_data.node: (kmem_cache#28-o0)->irq_data.node: 0
// desc->irq_data.affinity: (kmem_cache#28-o0)->irq_data.affinity,
// irq_default_affinity->bits[0]: 0xF
cpumask_copy(desc->irq_data.affinity, irq_default_affinity);
// desc->irq_data.affinity: (kmem_cache#28-o0)->irq_data.affinity.bits[0]: 0xF
#ifdef CONFIG_GENERIC_PENDING_IRQ // CONFIG_GENERIC_PENDING_IRQ=n
cpumask_clear(desc->pending_mask);
#endif
}// ARM10C 20141004
// 0, allocated_irqs
#define set_bit(nr,p) ATOMIC_BITOP(set_bit,nr,p) // _set_bit(nr,p)로 치환// ARM10C 20141004
// i: 0, desc: kmem_cache#28-o0
static void irq_insert_desc(unsigned int irq, struct irq_desc *desc)
{
// irq: 0, desc: kmem_cache#28-o0
radix_tree_insert(&irq_desc_tree, irq, desc);
// radix tree에 kmem_cache#28-o0를 노드로 추가
}// ARM10C 20141004
// &irq_desc_tree, irq: 0, desc: kmem_cache#28-o0
int radix_tree_insert(struct radix_tree_root *root,
unsigned long index, void *item)
{
struct radix_tree_node *node = NULL, *slot;
unsigned int height, shift;
int offset;
int error;
BUG_ON(radix_tree_is_indirect_ptr(item));
/* Make sure the tree is high enough. */
if (index > radix_tree_maxindex(root->height)) {
error = radix_tree_extend(root, index);
if (error)
return error;
}
slot = indirect_to_ptr(root->rnode);
height = root->height;
shift = (height-1) * RADIX_TREE_MAP_SHIFT;
offset = 0; /* uninitialised var warning */
while (height > 0) {
if (slot == NULL) {
/* Have to add a child node. */
if (!(slot = radix_tree_node_alloc(root)))
return -ENOMEM;
slot->height = height;
slot->parent = node;
if (node) {
rcu_assign_pointer(node->slots[offset], slot);
node->count++;
} else
rcu_assign_pointer(root->rnode, ptr_to_indirect(slot));
}
/* Go a level down */
offset = (index >> shift) & RADIX_TREE_MAP_MASK;
node = slot;
slot = node->slots[offset];
shift -= RADIX_TREE_MAP_SHIFT;
height--;
}
if (slot != NULL)
return -EEXIST;
if (node) {
node->count++;
rcu_assign_pointer(node->slots[offset], item);
BUG_ON(tag_get(node, 0, offset));
BUG_ON(tag_get(node, 1, offset));
} else {
rcu_assign_pointer(root->rnode, item);
BUG_ON(root_tag_get(root, 0));
BUG_ON(root_tag_get(root, 1));
}
return 0;
}
EXPORT_SYMBOL(radix_tree_insert);// ARM10C 20141004
int __init __weak arch_early_irq_init(void)
{
return 0;
}========
// 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();
}#define IS_ENABLED(option) \
(config_enabled(option) || config_enabled(option##_MODULE))#ifdef CONFIG_IRQCHIP // CONFIG_IRQCHIP=y
// ARM10C 20141004
void irqchip_init(void);
#else
static inline void irqchip_init(void) {}
#endif// 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();
}// ARM10C 20141004
void __init irqchip_init(void)
{
// exynos-combiner.c 에 정의된 함수를 사용하여 초기화 수행
// __irqchip_begin: irqchip_of_match_exynos4210_combiner
of_irq_init(__irqchip_begin);
}// ARM10C 20141004
// __irqchip_begin: irqchip_of_match_exynos4210_combiner
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의 주소
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
desc = kzalloc(sizeof(*desc), GFP_KERNEL);
// desc: kmem_cache#30-o10
// desc: kmem_cache#30-o10
if (WARN_ON(!desc))
goto err;
// desc->dev: (kmem_cache#30-o10)->dev, np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
desc->dev = np;
// desc->dev: (kmem_cache#30-o10)->dev: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
// 2014/10/04 종료
// desc->interrupt_parent: (kmem_cache#30-o10)->interrupt_parent, np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
desc->interrupt_parent = of_irq_find_parent(np);
if (desc->interrupt_parent == np)
desc->interrupt_parent = NULL;
list_add_tail(&desc->list, &intc_desc_list);
}
/*
* The root irq controller is the one without an interrupt-parent.
* That one goes first, followed by the controllers that reference it,
* followed by the ones that reference the 2nd level controllers, etc.
*/
while (!list_empty(&intc_desc_list)) {
/*
* Process all controllers with the current 'parent'.
* First pass will be looking for NULL as the parent.
* The assumption is that NULL parent means a root controller.
*/
list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
const struct of_device_id *match;
int ret;
of_irq_init_cb_t irq_init_cb;
if (desc->interrupt_parent != parent)
continue;
list_del(&desc->list);
match = of_match_node(matches, desc->dev);
if (WARN(!match->data,
"of_irq_init: no init function for %s\n",
match->compatible)) {
kfree(desc);
continue;
}
pr_debug("of_irq_init: init %s @ %p, parent %p\n",
match->compatible,
desc->dev, desc->interrupt_parent);
irq_init_cb = (of_irq_init_cb_t)match->data;
ret = irq_init_cb(desc->dev, desc->interrupt_parent);
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.
*/
list_add_tail(&desc->list, &intc_parent_list);
}
/* Get the next pending parent that might have children */
desc = list_first_entry_or_null(&intc_parent_list,
typeof(*desc), list);
if (!desc) {
pr_err("of_irq_init: children remain, but no parents\n");
break;
}
list_del(&desc->list);
parent = desc->dev;
kfree(desc);
}
list_for_each_entry_safe(desc, temp_desc, &intc_parent_list, list) {
list_del(&desc->list);
kfree(desc);
}
err:
list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
list_del(&desc->list);
kfree(desc);
}
} 6cd3763..d50372f master -> origin/master
Updating 6cd3763..d50372f
Fast-forward
arch/arm/include/asm/bitops.h | 2 +
arch/arm/include/asm/hw_irq.h | 3 +
arch/arm/include/asm/irq.h | 7 +-
arch/arm/kernel/irq.c | 9 +-
arch/arm/kernel/vmlinux.lds.S | 5 +-
arch/arm/lib/setbit.S | 4 +-
drivers/irqchip/exynos-combiner.c | 5 +
drivers/irqchip/irqchip.c | 4 +
drivers/irqchip/irqchip.h | 1 +
drivers/of/base.c | 107 ++++++++++++++++++++-
drivers/of/irq.c | 49 +++++++++-
include/asm-generic/vmlinux.lds.h | 3 +-
include/linux/bitmap.h | 10 ++
include/linux/bitops.h | 5 +
include/linux/compiler.h | 1 +
include/linux/context_tracking.h | 3 +-
include/linux/cpu.h | 9 ++
include/linux/cpumask.h | 18 ++++
include/linux/gfp.h | 4 +
include/linux/irq.h | 32 +++++++
include/linux/irqchip.h | 3 +-
include/linux/irqdesc.h | 10 +-
include/linux/kernel.h | 2 +
include/linux/list.h | 1 +
include/linux/lockdep.h | 2 +
include/linux/mod_devicetable.h | 1 +
include/linux/nodemask.h | 2 +
include/linux/of.h | 17 +++-
include/linux/percpu.h | 2 +
include/linux/radix-tree.h | 25 +++++
include/linux/slab.h | 63 ++++++++++++-
include/linux/tick.h | 3 +-
include/linux/types.h | 3 +
include/linux/wait.h | 4 +
init/main.c | 13 ++-
kernel/cpu.c | 7 ++
kernel/irq/dummychip.c | 1 +
kernel/irq/handle.c | 1 +
kernel/irq/internals.h | 9 +-
kernel/irq/irqdesc.c | 193 ++++++++++++++++++++++++++++++++++++--
kernel/irq/manage.c | 3 +-
kernel/irq/settings.h | 13 +++
kernel/notifier.c | 5 +
kernel/rcu/tree.c | 1 +
kernel/softirq.c | 1 +
lib/radix-tree.c | 81 ++++++++++++++++
mm/percpu.c | 2 +
mm/slab_common.c | 7 ++
mm/slub.c | 2 +
49 files changed, 730 insertions(+), 28 deletions(-)