static void __init intc_register_irq()

in intc/core.c [73:162]


static void __init intc_register_irq(struct intc_desc *desc,
				     struct intc_desc_int *d,
				     intc_enum enum_id,
				     unsigned int irq)
{
	struct intc_handle_int *hp;
	struct irq_data *irq_data;
	unsigned int data[2], primary;
	unsigned long flags;

	raw_spin_lock_irqsave(&intc_big_lock, flags);
	radix_tree_insert(&d->tree, enum_id, intc_irq_xlate_get(irq));
	raw_spin_unlock_irqrestore(&intc_big_lock, flags);

	/*
	 * Prefer single interrupt source bitmap over other combinations:
	 *
	 * 1. bitmap, single interrupt source
	 * 2. priority, single interrupt source
	 * 3. bitmap, multiple interrupt sources (groups)
	 * 4. priority, multiple interrupt sources (groups)
	 */
	data[0] = intc_get_mask_handle(desc, d, enum_id, 0);
	data[1] = intc_get_prio_handle(desc, d, enum_id, 0);

	primary = 0;
	if (!data[0] && data[1])
		primary = 1;

	if (!data[0] && !data[1])
		pr_warn("missing unique irq mask for irq %d (vect 0x%04x)\n",
			irq, irq2evt(irq));

	data[0] = data[0] ? data[0] : intc_get_mask_handle(desc, d, enum_id, 1);
	data[1] = data[1] ? data[1] : intc_get_prio_handle(desc, d, enum_id, 1);

	if (!data[primary])
		primary ^= 1;

	BUG_ON(!data[primary]); /* must have primary masking method */

	irq_data = irq_get_irq_data(irq);

	disable_irq_nosync(irq);
	irq_set_chip_and_handler_name(irq, &d->chip, handle_level_irq,
				      "level");
	irq_set_chip_data(irq, (void *)data[primary]);

	/*
	 * set priority level
	 */
	intc_set_prio_level(irq, intc_get_dfl_prio_level());

	/* enable secondary masking method if present */
	if (data[!primary])
		_intc_enable(irq_data, data[!primary]);

	/* add irq to d->prio list if priority is available */
	if (data[1]) {
		hp = d->prio + d->nr_prio;
		hp->irq = irq;
		hp->handle = data[1];

		if (primary) {
			/*
			 * only secondary priority should access registers, so
			 * set _INTC_FN(h) = REG_FN_ERR for intc_set_priority()
			 */
			hp->handle &= ~_INTC_MK(0x0f, 0, 0, 0, 0, 0);
			hp->handle |= _INTC_MK(REG_FN_ERR, 0, 0, 0, 0, 0);
		}
		d->nr_prio++;
	}

	/* add irq to d->sense list if sense is available */
	data[0] = intc_get_sense_handle(desc, d, enum_id);
	if (data[0]) {
		(d->sense + d->nr_sense)->irq = irq;
		(d->sense + d->nr_sense)->handle = data[0];
		d->nr_sense++;
	}

	/* irq should be disabled by default */
	d->chip.irq_mask(irq_data);

	intc_set_ack_handle(irq, desc, d, enum_id);
	intc_set_dist_handle(irq, desc, d, enum_id);

	activate_irq(irq);
}