Unverified Commit 74ea6865 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!12369 x86/ioapic: Handle allocation failures gracefully

parents 41255614 010a654d
Loading
Loading
Loading
Loading
+22 −24
Original line number Diff line number Diff line
@@ -358,27 +358,26 @@ static void ioapic_mask_entry(int apic, int pin)
 * shared ISA-space IRQs, so we have to support them. We are super
 * fast in the common case, and fast for shared ISA-space IRQs.
 */
static int __add_pin_to_irq_node(struct mp_chip_data *data,
				 int node, int apic, int pin)
static bool add_pin_to_irq_node(struct mp_chip_data *data, int node, int apic, int pin)
{
	struct irq_pin_list *entry;

	/* don't allow duplicates */
	for_each_irq_pin(entry, data->irq_2_pin)
	/* Don't allow duplicates */
	for_each_irq_pin(entry, data->irq_2_pin) {
		if (entry->apic == apic && entry->pin == pin)
			return 0;
			return true;
	}

	entry = kzalloc_node(sizeof(struct irq_pin_list), GFP_ATOMIC, node);
	if (!entry) {
		pr_err("can not alloc irq_pin_list (%d,%d,%d)\n",
		       node, apic, pin);
		return -ENOMEM;
		pr_err("Cannot allocate irq_pin_list (%d,%d,%d)\n", node, apic, pin);
		return false;
	}

	entry->apic = apic;
	entry->pin = pin;
	list_add_tail(&entry->list, &data->irq_2_pin);

	return 0;
	return true;
}

static void __remove_pin_from_irq(struct mp_chip_data *data, int apic, int pin)
@@ -393,13 +392,6 @@ static void __remove_pin_from_irq(struct mp_chip_data *data, int apic, int pin)
		}
}

static void add_pin_to_irq_node(struct mp_chip_data *data,
				int node, int apic, int pin)
{
	if (__add_pin_to_irq_node(data, node, apic, pin))
		panic("IO-APIC: failed to add irq-pin. Can not proceed\n");
}

/*
 * Reroute an IRQ to a different pin.
 */
@@ -1001,8 +993,7 @@ static int alloc_isa_irq_from_domain(struct irq_domain *domain,
	if (irq_data && irq_data->parent_data) {
		if (!mp_check_pin_attr(irq, info))
			return -EBUSY;
		if (__add_pin_to_irq_node(irq_data->chip_data, node, ioapic,
					  info->ioapic.pin))
		if (!add_pin_to_irq_node(irq_data->chip_data, node, ioapic, info->ioapic.pin))
			return -ENOMEM;
	} else {
		info->flags |= X86_IRQ_ALLOC_LEGACY;
@@ -3032,10 +3023,8 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,

	info->ioapic.entry = &data->entry;
	ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, info);
	if (ret < 0) {
		kfree(data);
		return ret;
	}
	if (ret < 0)
		goto free_data;

	INIT_LIST_HEAD(&data->irq_2_pin);
	irq_data->hwirq = info->ioapic.pin;
@@ -3045,7 +3034,10 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,
	mp_irqdomain_get_attr(mp_pin_to_gsi(ioapic, pin), data, info);

	cfg = irqd_cfg(irq_data);
	add_pin_to_irq_node(data, ioapic_alloc_attr_node(info), ioapic, pin);
	if (!add_pin_to_irq_node(data, ioapic_alloc_attr_node(info), ioapic, pin)) {
		ret = -ENOMEM;
		goto free_irqs;
	}

	local_irq_save(flags);
	if (info->ioapic.entry)
@@ -3061,6 +3053,12 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,
		    virq, data->trigger, data->polarity, cfg->dest_apicid);

	return 0;

free_irqs:
	irq_domain_free_irqs_parent(domain, virq, nr_irqs);
free_data:
	kfree(data);
	return ret;
}

void mp_irqdomain_free(struct irq_domain *domain, unsigned int virq,