diff options
Diffstat (limited to 'arch/x86/kernel/devicetree.c')
| -rw-r--r-- | arch/x86/kernel/devicetree.c | 51 | 
1 files changed, 42 insertions, 9 deletions
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c index 3ae2ced4a87..b1581527a23 100644 --- a/arch/x86/kernel/devicetree.c +++ b/arch/x86/kernel/devicetree.c @@ -342,6 +342,47 @@ const struct irq_domain_ops ioapic_irq_domain_ops = {  	.xlate = ioapic_xlate,  }; +static void dt_add_ioapic_domain(unsigned int ioapic_num, +		struct device_node *np) +{ +	struct irq_domain *id; +	struct mp_ioapic_gsi *gsi_cfg; +	int ret; +	int num; + +	gsi_cfg = mp_ioapic_gsi_routing(ioapic_num); +	num = gsi_cfg->gsi_end - gsi_cfg->gsi_base + 1; + +	id = irq_domain_add_linear(np, num, &ioapic_irq_domain_ops, +			(void *)ioapic_num); +	BUG_ON(!id); +	if (gsi_cfg->gsi_base == 0) { +		/* +		 * The first NR_IRQS_LEGACY irq descs are allocated in +		 * early_irq_init() and need just a mapping. The +		 * remaining irqs need both. All of them are preallocated +		 * and assigned so we can keep the 1:1 mapping which the ioapic +		 * is having. +		 */ +		ret = irq_domain_associate_many(id, 0, 0, NR_IRQS_LEGACY); +		if (ret) +			pr_err("Error mapping legacy IRQs: %d\n", ret); + +		if (num > NR_IRQS_LEGACY) { +			ret = irq_create_strict_mappings(id, NR_IRQS_LEGACY, +					NR_IRQS_LEGACY, num - NR_IRQS_LEGACY); +			if (ret) +				pr_err("Error creating mapping for the " +						"remaining IRQs: %d\n", ret); +		} +		irq_set_default_host(id); +	} else { +		ret = irq_create_strict_mappings(id, gsi_cfg->gsi_base, 0, num); +		if (ret) +			pr_err("Error creating IRQ mapping: %d\n", ret); +	} +} +  static void __init ioapic_add_ofnode(struct device_node *np)  {  	struct resource r; @@ -356,15 +397,7 @@ static void __init ioapic_add_ofnode(struct device_node *np)  	for (i = 0; i < nr_ioapics; i++) {  		if (r.start == mpc_ioapic_addr(i)) { -			struct irq_domain *id; -			struct mp_ioapic_gsi *gsi_cfg; - -			gsi_cfg = mp_ioapic_gsi_routing(i); - -			id = irq_domain_add_legacy(np, 32, gsi_cfg->gsi_base, 0, -						   &ioapic_irq_domain_ops, -						   (void*)i); -			BUG_ON(!id); +			dt_add_ioapic_domain(i, np);  			return;  		}  	}  |