Пример #1
0
/**
 * irq_alloc_descs - allocate and initialize a range of irq descriptors
 * @irq:	Allocate for specific irq number if irq >= 0
 * @from:	Start the search from this irq number
 * @cnt:	Number of consecutive irqs to allocate.
 * @node:	Preferred node on which the irq descriptor should be allocated
 * @owner:	Owning module (can be NULL)
 *
 * Returns the first irq number or error code
 */
int __ref
__irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
		  struct module *owner)
{
	int start, ret;

	if (!cnt)
		return -EINVAL;

	if (irq >= 0) {
		if (from > irq)
			return -EINVAL;
		from = irq;
	} else {
		/*
		 * For interrupts which are freely allocated the
		 * architecture can force a lower bound to the @from
		 * argument. x86 uses this to exclude the GSI space.
		 */
		from = arch_dynirq_lower_bound(from);
	}

	mutex_lock(&sparse_irq_lock);

	start = bitmap_find_next_zero_area(allocated_irqs, IRQ_BITMAP_BITS,
					   from, cnt, 0);
	ret = -EEXIST;
	if (irq >=0 && start != irq)
		goto err;

	if (start + cnt > nr_irqs) {
		ret = irq_expand_nr_irqs(start + cnt);
		if (ret)
			goto err;
	}

	bitmap_set(allocated_irqs, start, cnt);
	mutex_unlock(&sparse_irq_lock);
	return alloc_descs(start, cnt, node, owner);

err:
	mutex_unlock(&sparse_irq_lock);
	return ret;
}
Пример #2
0
/**
 * irq_alloc_descs - allocate and initialize a range of irq descriptors
 * @irq:	Allocate for specific irq number if irq >= 0
 * @from:	Start the search from this irq number
 * @cnt:	Number of consecutive irqs to allocate.
 * @node:	Preferred node on which the irq descriptor should be allocated
 * @owner:	Owning module (can be NULL)
 *
 * Returns the first irq number or error code
 */
int __ref
__irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
		  struct module *owner)
{
	int start, ret;

	if (!cnt)
		return -EINVAL;

	if (irq >= 0) {
		if (from > irq)
			return -EINVAL;
		from = irq;
	}

	mutex_lock(&sparse_irq_lock);

	start = bitmap_find_next_zero_area(allocated_irqs, IRQ_BITMAP_BITS,
					   from, cnt, 0);
	ret = -EEXIST;
	if (irq >=0 && start != irq)
		goto err;

	if (start + cnt > nr_irqs) {
		ret = irq_expand_nr_irqs(start + cnt);
		if (ret)
			goto err;
	}
	
	bitmap_set(allocated_irqs, start, cnt);
	mutex_unlock(&sparse_irq_lock);
	
	return alloc_descs(start, cnt, node, owner);

err:
	mutex_unlock(&sparse_irq_lock);
	return ret;
}
Пример #3
0
// ARM10C 20141115
// irq_start: -1, 16, gic_irqs: 144, numa_node_id(): 0, THIS_MODULE: ((struct module *)0)
// ARM10C 20141213
// first_irq: 160, 160, size: 256, 0, THIS_MODULE: ((struct module *)0)
int __ref
__irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
		  struct module *owner)
{
	int start, ret;

	// cnt: 144
	// cnt: 256
	if (!cnt)
		return -EINVAL;

	// irq: -1
	// irq: 160
	if (irq >= 0) {
		// from: 160, irq: 160
		if (from > irq)
			return -EINVAL;

		// from: 160, irq: 160
		from = irq;
		// from: 160
	}

	mutex_lock(&sparse_irq_lock);
	// sparse_irq_lock을 이용한 mutex lock 수행
	// sparse_irq_lock을 이용한 mutex lock 수행

	// IRQ_BITMAP_BITS: 8212, from: 16, cnt: 144
	// bitmap_find_next_zero_area(allocated_irqs, 8212, 16, 144, 0): 16
	// IRQ_BITMAP_BITS: 8212, from: 160, cnt: 256
	// bitmap_find_next_zero_area(allocated_irqs, 8212, 160, 256, 0): 160
	start = bitmap_find_next_zero_area(allocated_irqs, IRQ_BITMAP_BITS,
					   from, cnt, 0);
	// start: 16
	// start: 160

	// EEXIST: 17
	// EEXIST: 17
	ret = -EEXIST;
	// ret: -17
	// ret: -17

	// irq: -1, start: 16
	// irq: 160, start: 160
	if (irq >=0 && start != irq)
		goto err;

	// start: 16, cnt: 144, nr_irqs: 16
	// start: 160, cnt: 256, nr_irqs: 160
	if (start + cnt > nr_irqs) {
		// start: 16, cnt: 144
		// irq_expand_nr_irqs(160): 0
		// start: 160, cnt: 256
		// irq_expand_nr_irqs(416): 0
		ret = irq_expand_nr_irqs(start + cnt);
		// ret: 0
		// ret: 0

		// irq_expand_nr_irqs(160)에서 한일:
		// 전역변수 nr_irqs 값을 160으로 갱신

		// irq_expand_nr_irqs(416)에서 한일:
		// 전역변수 nr_irqs 값을 416으로 갱신

		// ret: 0
		// ret: 0
		if (ret)
			goto err;
	}

	// start: 16, cnt: 144
	// start: 160, cnt: 256
	bitmap_set(allocated_irqs, start, cnt);

	// bitmap_set(16, 144)에서 한일:
	// allocated_irqs 의 16 bit 부터 144 bit 만큼을 1로 set

	// bitmap_set(160, 256)에서 한일:
	// allocated_irqs 의 160 bit 부터 256 bit 만큼을 1로 set

	mutex_unlock(&sparse_irq_lock);
	// sparse_irq_lock을 이용한 mutex unlock 수행
	// sparse_irq_lock을 이용한 mutex unlock 수행

	// start: 16, cnt: 144, node: 0, owner: NULL
	// alloc_descs(16, 144, 0, NULL): 16
	// start: 160, cnt: 256, node: 0, owner: NULL
	// alloc_descs(160, 256, 0, NULL): 160
	return alloc_descs(start, cnt, node, owner);
	// return 16
	// return 160

	/*
	// alloc_descs(16)에서 한일:
	// struct irq_desc의 자료 구조크기 만큼 160개의 메모리를 할당 받아
	// radix tree 구조로 구성
	//
	// 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: 64
	// (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: 64
	// (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)
	//
	// (&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      |
	//     +-----------------------+  +-----------------------+  +-----------------------+
	*/

	/*
	// alloc_descs(160)에서 한일:
	// struct irq_desc의 자료 구조크기 만큼 256개의 메모리를 할당 받아
	// radix tree 구조로 구성
	//
	// irq 160 ~ 415를 위한 struct irq_desc 메모리를 할당 받아 초기화 수행
	// (kmem_cache#28-oX (irq 160...415))->lock 을 이용한 spinlock 초기화 수행
	// (kmem_cache#28-oX (irq 160...415))->status_use_accessors: 0xc00
	// (kmem_cache#28-oX (irq 160...415))->handle_irq: handle_bad_irq
	// (kmem_cache#28-oX (irq 160...415))->depth: 1
	// (kmem_cache#28-oX (irq 160...415))->irq_count: 0
	// (kmem_cache#28-oX (irq 160...415))->irqs_unhandled: 0
	// (kmem_cache#28-oX (irq 160...415))->name: NULL
	// (kmem_cache#28-oX (irq 160...415))->owner: null
	// (kmem_cache#28-oX (irq 160...415))->kstat_irqs: pcp 4 byte 공간
	// [pcp0...3] (kmem_cache#28-oX (irq 160...415))->kstat_irqs: 0
	// (kmem_cache#28-oX (irq 160...415))->irq_data.irq: 16...415
	// (kmem_cache#28-oX (irq 160...415))->irq_data.chip: &no_irq_chip
	// (kmem_cache#28-oX (irq 160...415))->irq_data.chip_data: NULL
	// (kmem_cache#28-oX (irq 160...415))->irq_data.handler_data: NULL
	// (kmem_cache#28-oX (irq 160...415))->irq_data.msi_desc: NULL
	// (kmem_cache#28-oX (irq 160...415))->irq_data.state_use_accessors: 0x10000
	// (kmem_cache#28-oX (irq 160...415))->irq_data.node: 0
	// (kmem_cache#28-oX (irq 160...415))->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: 7
	// (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-o1)->slots[3]: kmem_cache#20-o4 (radix height 1 관리 주소)
	// (kmem_cache#20-o1)->slots[4]: kmem_cache#20-o5 (radix height 1 관리 주소)
	// (kmem_cache#20-o1)->slots[5]: kmem_cache#20-o6 (radix height 1 관리 주소)
	// (kmem_cache#20-o1)->slots[6]: kmem_cache#20-o7 (radix height 1 관리 주소)
	//
	// (kmem_cache#20-o0)->height: 1
	// (kmem_cache#20-o0)->count: 64
	// (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: 64
	// (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: 64
	// (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...191)
	//
	// (kmem_cache#20-o4)->height: 1
	// (kmem_cache#20-o4)->count: 64
	// (kmem_cache#20-o4)->parent: kmem_cache#20-o1 (RADIX_LSB: 1)
	// (kmem_cache#20-o4)->slots[0...63]: kmem_cache#28-oX (irq 192...255)
	//
	// (kmem_cache#20-o5)->height: 1
	// (kmem_cache#20-o5)->count: 64
	// (kmem_cache#20-o5)->parent: kmem_cache#20-o1 (RADIX_LSB: 1)
	// (kmem_cache#20-o5)->slots[0...63]: kmem_cache#28-oX (irq 256...319)
	//
	// (kmem_cache#20-o6)->height: 1
	// (kmem_cache#20-o6)->count: 64
	// (kmem_cache#20-o6)->parent: kmem_cache#20-o1 (RADIX_LSB: 1)
	// (kmem_cache#20-o6)->slots[0...63]: kmem_cache#28-oX (irq 320...383)
	//
	// (kmem_cache#20-o7)->height: 1
	// (kmem_cache#20-o7)->count: 32
	// (kmem_cache#20-o7)->parent: kmem_cache#20-o1 (RADIX_LSB: 1)
	// (kmem_cache#20-o7)->slots[0...31]: kmem_cache#28-oX (irq 384...415)
	//
	// (&irq_desc_tree)->rnode -->  +-----------------------+
	//                              |    radix_tree_node    |
	//                              |   (kmem_cache#20-o1)  |
	//                              +-----------------------+
	//                              | height: 2 | count: 7  |
	//                              +-----------------------+
	//                              | radix_tree_node 0 ~ 6 | \
	//                            / +-----------------------+ \ \
	//                          /  /           |  |          \  \ \ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
	//  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: 64 |   |
	//  +-----------------------+ | +-----------------------+ | +-----------------------+   |
	//  |    irq  0 ~ 63        | | |    irq 64 ~ 127       | | |    irq 128 ~ 191      |   |
	//  +-----------------------+ | +-----------------------+ | +-----------------------+   |
	//                           /                |            \                            |
	//  slot: 3                /    slot: 4       |              \                slot: 5    \                slot: 6
	//  +-----------------------+   +-----------------------+   +-----------------------+   +-----------------------+
	//  |    radix_tree_node    |   |    radix_tree_node    |   |    radix_tree_node    |   |    radix_tree_node    |
	//  |   (kmem_cache#20-o4)  |   |   (kmem_cache#20-o5)  |   |   (kmem_cache#20-o6)  |   |   (kmem_cache#20-o7)  |
	//  +-----------------------+   +-----------------------+   +-----------------------+   +-----------------------+
	//  | height: 1 | count: 64 |   | height: 1 | count: 64 |   | height: 1 | count: 64 |   | height: 1 | count: 32 |
	//  +-----------------------+   +-----------------------+   +-----------------------+   +-----------------------+
	//  |    irq  192 ~ 255     |   |    irq 256 ~ 319      |   |    irq 320 ~ 383      |   |    irq 384 ~ 415      |
	//  +-----------------------+   +-----------------------+   +-----------------------+   +-----------------------+
	*/
err:
	mutex_unlock(&sparse_irq_lock);
	return ret;
}