static int alloc_descs(unsigned int start, unsigned int cnt, int node, struct module *owner) { struct irq_desc *desc; int i; for (i = 0; i < cnt; i++) { desc = alloc_desc(start + i, node, owner); if (!desc) goto err; mutex_lock(&sparse_irq_lock); irq_insert_desc(start + i, desc); mutex_unlock(&sparse_irq_lock); } return start; err: for (i--; i >= 0; i--) free_desc(start + i); mutex_lock(&sparse_irq_lock); bitmap_clear(allocated_irqs, start, cnt); mutex_unlock(&sparse_irq_lock); return -ENOMEM; }
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 %d\n", NR_IRQS, nr_irqs, initcnt); if (WARN_ON(nr_irqs > IRQ_BITMAP_BITS)) nr_irqs = IRQ_BITMAP_BITS; if (WARN_ON(initcnt > IRQ_BITMAP_BITS)) initcnt = IRQ_BITMAP_BITS; if (initcnt > nr_irqs) nr_irqs = initcnt; for (i = 0; i < initcnt; i++) { desc = alloc_desc(i, node, NULL); set_bit(i, allocated_irqs); irq_insert_desc(i, desc); } return arch_early_irq_init(); }
int16 InsTime(uint32 tm, uint16 trap) { D(bug("InsTime %08lx, trap %04x\n", tm, trap)); WriteMacInt16(tm + qType, ReadMacInt16(tm + qType) & 0x1fff | (trap << 4) & 0x6000); if (find_desc(tm) >= 0) printf("WARNING: InsTime(): Task re-inserted\n"); else { int i = alloc_desc(tm); if (i < 0) printf("FATAL: InsTime(): No free Time Manager descriptor\n"); } return 0; }
static int alloc_descs(unsigned int start, unsigned int cnt, int node, const struct irq_affinity_desc *affinity, struct module *owner) { struct irq_desc *desc; int i; /* Validate affinity mask(s) */ if (affinity) { for (i = 0; i < cnt; i++) { if (cpumask_empty(&affinity[i].mask)) return -EINVAL; } } for (i = 0; i < cnt; i++) { const struct cpumask *mask = NULL; unsigned int flags = 0; if (affinity) { if (affinity->is_managed) { flags = IRQD_AFFINITY_MANAGED | IRQD_MANAGED_SHUTDOWN; } mask = &affinity->mask; node = cpu_to_node(cpumask_first(mask)); affinity++; } desc = alloc_desc(start + i, node, flags, mask, owner); if (!desc) goto err; irq_insert_desc(start + i, desc); irq_sysfs_add(start + i, desc); irq_add_debugfs_entry(start + i, desc); } bitmap_set(allocated_irqs, start, cnt); return start; err: for (i--; i >= 0; i--) free_desc(start + i); return -ENOMEM; }
static int alloc_descs(unsigned int start, unsigned int cnt, int node, const struct cpumask *affinity, struct module *owner) { const struct cpumask *mask = NULL; struct irq_desc *desc; unsigned int flags; int i; /* Validate affinity mask(s) */ if (affinity) { for (i = 0, mask = affinity; i < cnt; i++, mask++) { if (cpumask_empty(mask)) return -EINVAL; } } flags = affinity ? IRQD_AFFINITY_MANAGED : 0; mask = NULL; for (i = 0; i < cnt; i++) { if (affinity) { node = cpu_to_node(cpumask_first(affinity)); mask = affinity; affinity++; } desc = alloc_desc(start + i, node, flags, mask, owner); if (!desc) goto err; mutex_lock(&sparse_irq_lock); irq_insert_desc(start + i, desc); irq_sysfs_add(start + i, desc); mutex_unlock(&sparse_irq_lock); } return start; err: for (i--; i >= 0; i--) free_desc(start + i); mutex_lock(&sparse_irq_lock); bitmap_clear(allocated_irqs, start, cnt); mutex_unlock(&sparse_irq_lock); return -ENOMEM; }
// 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 // 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를 노드로 추가 // irq_insert_desc(0)에서 한일: // ((&irq_desc_tree)->rnode) = (typeof(*kmem_cache#28-o0) __force rcu *)(kmem_cache#28-o0); // // irq_insert_desc(1)에서 한일: // radix_tree_node_cachep를 사용한 struct radix_tree_node 용 메모리 할당: kmem_cache#20-o0 // (kmem_cache#20-o0)->height: 1 // (kmem_cache#20-o0)->count: 1 // (kmem_cache#20-o0)->parent: NULL // (kmem_cache#20-o0)->slots[0]: kmem_cache#28-o0 (irq 0) // (kmem_cache#20-o0)->slots[1]: kmem_cache#28-o1 (irq 1) // radix tree의 root node: &irq_desc_tree 값을 변경 // (&irq_desc_tree)->rnode: kmem_cache#20-o0 (RADIX_LSB: 1) // (&irq_desc_tree)->height: 1 // // irq_insert_desc(2)에서 한일: // (kmem_cache#20-o0)->count: 2 // (kmem_cache#20-o0)->slots[2]: kmem_cache#28-o2 (irq 2) // i: 1 ... 15 수행 } // arch_early_irq_init(): 0 return arch_early_irq_init(); // return 0 }
// ARM10C 20141115 // start: 16, cnt: 144, node: 0, owner: NULL // ARM10C 20141213 // start: 160, cnt: 256, node: 0, owner: NULL static int alloc_descs(unsigned int start, unsigned int cnt, int node, struct module *owner) { struct irq_desc *desc; int i; // cnt: 144 for (i = 0; i < cnt; i++) { // i: 0, start: 16, node: 0, owner: NULL // alloc_desc(16, 0, NULL): kmem_cache#28-oX (irq 16) // i: 48, start: 16, node: 0, owner: NULL // alloc_desc(64, 0, NULL): kmem_cache#28-oX (irq 64) desc = alloc_desc(start + i, node, owner); // desc: kmem_cache#28-oX (irq 16) // desc: kmem_cache#28-oX (irq 64) // alloc_desc(16)에서 한일: // (kmem_cache#28-oX)->kstat_irqs: pcp 4 byte 공간 // (kmem_cache#28-oX)->lock 을 이용한 spinlock 초기화 수행 // (kmem_cache#28-oX)->irq_data.irq: 16 // (kmem_cache#28-oX)->irq_data.chip: &no_irq_chip // (kmem_cache#28-oX)->irq_data.chip_data: NULL // (kmem_cache#28-oX)->irq_data.handler_data: NULL // (kmem_cache#28-oX)->irq_data.msi_desc: NULL // (kmem_cache#28-oX)->status_use_accessors: 0xc00 // (&(kmem_cache#28-oX)->irq_data)->state_use_accessors: 0x10000 // (kmem_cache#28-oX)->handle_irq: handle_bad_irq // (kmem_cache#28-oX)->depth: 1 // (kmem_cache#28-oX)->irq_count: 0 // (kmem_cache#28-oX)->irqs_unhandled: 0 // (kmem_cache#28-oX)->name: NULL // (kmem_cache#28-oX)->owner: null // [pcp0...3] (kmem_cache#28-oX)->kstat_irqs: 0 // (kmem_cache#28-oX)->irq_data.node: 0 // (kmem_cache#28-oX)->irq_data.affinity.bits[0]: 0xF // alloc_desc(64)에서 한일: // (kmem_cache#28-oX)->kstat_irqs: pcp 4 byte 공간 // (kmem_cache#28-oX)->lock 을 이용한 spinlock 초기화 수행 // (kmem_cache#28-oX)->irq_data.irq: 64 // (kmem_cache#28-oX)->irq_data.chip: &no_irq_chip // (kmem_cache#28-oX)->irq_data.chip_data: NULL // (kmem_cache#28-oX)->irq_data.handler_data: NULL // (kmem_cache#28-oX)->irq_data.msi_desc: NULL // (kmem_cache#28-oX)->status_use_accessors: 0xc00 // (&(kmem_cache#28-oX)->irq_data)->state_use_accessors: 0x10000 // (kmem_cache#28-oX)->handle_irq: handle_bad_irq // (kmem_cache#28-oX)->depth: 1 // (kmem_cache#28-oX)->irq_count: 0 // (kmem_cache#28-oX)->irqs_unhandled: 0 // (kmem_cache#28-oX)->name: NULL // (kmem_cache#28-oX)->owner: null // [pcp0...3] (kmem_cache#28-oX)->kstat_irqs: 0 // (kmem_cache#28-oX)->irq_data.node: 0 // (kmem_cache#28-oX)->irq_data.affinity.bits[0]: 0xF // desc: kmem_cache#28-oX (irq 16) // desc: kmem_cache#28-oX (irq 64) if (!desc) goto err; mutex_lock(&sparse_irq_lock); // sparse_irq_lock을 이용한 mutex lock 수행 // sparse_irq_lock을 이용한 mutex lock 수행 // i: 0, start: 16, desc: kmem_cache#28-oX (irq 16), irq_insert_desc(16, kmem_cache#28-oX (irq 16)): 0 // i: 48, start: 16, desc: kmem_cache#28-oX (irq 64), irq_insert_desc(48, kmem_cache#28-oX (irq 64)): 0 irq_insert_desc(start + i, desc); // 2014/11/15 종료 // 2014/11/22 시작 // irq_insert_desc(16)에서 한일: // (kmem_cache#20-o0)->count: 16 // (kmem_cache#20-o0)->slots[16]: kmem_cache#28-o16 (irq 16) mutex_unlock(&sparse_irq_lock); // sparse_irq_lock을 이용한 mutex unlock 수행 // sparse_irq_lock을 이용한 mutex unlock 수행 // i: 1 ... 143 까지 루프 수행 } /* // 위 loop의 수행 결과 // // irq 16 ~ 159를 위한 struct irq_desc 메모리를 할당 받아 초기화 수행 // (kmem_cache#28-oX (irq 16...159))->lock 을 이용한 spinlock 초기화 수행 // (kmem_cache#28-oX (irq 16...159))->status_use_accessors: 0xc00 // (kmem_cache#28-oX (irq 16...159))->handle_irq: handle_bad_irq // (kmem_cache#28-oX (irq 16...159))->depth: 1 // (kmem_cache#28-oX (irq 16...159))->irq_count: 0 // (kmem_cache#28-oX (irq 16...159))->irqs_unhandled: 0 // (kmem_cache#28-oX (irq 16...159))->name: NULL // (kmem_cache#28-oX (irq 16...159))->owner: null // (kmem_cache#28-oX (irq 16...159))->kstat_irqs: pcp 4 byte 공간 // [pcp0...3] (kmem_cache#28-oX (irq 16...159))->kstat_irqs: 0 // (kmem_cache#28-oX (irq 16...159))->irq_data.irq: 16...159 // (kmem_cache#28-oX (irq 16...159))->irq_data.chip: &no_irq_chip // (kmem_cache#28-oX (irq 16...159))->irq_data.chip_data: NULL // (kmem_cache#28-oX (irq 16...159))->irq_data.handler_data: NULL // (kmem_cache#28-oX (irq 16...159))->irq_data.msi_desc: NULL // (kmem_cache#28-oX (irq 16...159))->irq_data.state_use_accessors: 0x10000 // (kmem_cache#28-oX (irq 16...159))->irq_data.node: 0 // (kmem_cache#28-oX (irq 16...159))->irq_data.affinity.bits[0]: 0xF // // radix tree의 root node: &irq_desc_tree 값을 변경 // (&irq_desc_tree)->rnode: kmem_cache#20-o1 (RADIX_LSB: 1) // (&irq_desc_tree)->height: 2 // // (kmem_cache#20-o1)->height: 2 // (kmem_cache#20-o1)->count: 3 // (kmem_cache#20-o1)->parent: NULL // (kmem_cache#20-o1)->slots[0]: kmem_cache#20-o0 (radix height 1 관리 주소) // (kmem_cache#20-o1)->slots[1]: kmem_cache#20-o2 (radix height 1 관리 주소) // (kmem_cache#20-o1)->slots[2]: kmem_cache#20-o3 (radix height 1 관리 주소) // // (kmem_cache#20-o0)->height: 1 // (kmem_cache#20-o0)->count: 63 // (kmem_cache#20-o0)->parent: kmem_cache#20-o1 (RADIX_LSB: 1) // (kmem_cache#20-o0)->slots[0...63]: kmem_cache#28-oX (irq 0...63) // // (kmem_cache#20-o2)->height: 1 // (kmem_cache#20-o2)->count: 63 // (kmem_cache#20-o2)->parent: kmem_cache#20-o1 (RADIX_LSB: 1) // (kmem_cache#20-o2)->slots[0...63]: kmem_cache#28-oX (irq 63...127) // // (kmem_cache#20-o3)->height: 1 // (kmem_cache#20-o3)->count: 32 // (kmem_cache#20-o3)->parent: kmem_cache#20-o1 (RADIX_LSB: 1) // (kmem_cache#20-o3)->slots[0...63]: kmem_cache#28-oX (irq 127...159) // // 위 loop의 수행 결과를 나타낸 그림 // // (&irq_desc_tree)->rnode --> +-----------------------+ // | radix_tree_node | // | (kmem_cache#20-o1) | // +-----------------------+ // | height: 2 | count: 3 | // +-----------------------+ // | radix_tree_node 0 ~ 2 | // +-----------------------+ // / | \ // slot: 0 / slot: 1 | \ slot: 2 // +-----------------------+ +-----------------------+ +-----------------------+ // | radix_tree_node | | radix_tree_node | | radix_tree_node | // | (kmem_cache#20-o0) | | (kmem_cache#20-o2) | | (kmem_cache#20-o3) | // +-----------------------+ +-----------------------+ +-----------------------+ // | height: 1 | count: 64 | | height: 1 | count: 64 | | height: 1 | count: 32 | // +-----------------------+ +-----------------------+ +-----------------------+ // | irq 0 ~ 63 | | irq 64 ~ 127 | | irq 128 ~ 159 | // +-----------------------+ +-----------------------+ +-----------------------+ */ // start: 16 return start; // return 16 err: for (i--; i >= 0; i--) free_desc(start + i); mutex_lock(&sparse_irq_lock); bitmap_clear(allocated_irqs, start, cnt); mutex_unlock(&sparse_irq_lock); return -ENOMEM; }