Commit 930a1bbb authored by Johan Hovold's avatar Johan Hovold Committed by Marc Zyngier
Browse files

irqdomain: Clean up irq_domain_push/pop_irq()



The irq_domain_push_irq() interface is used to add a new (outmost) level
to a hierarchical domain after IRQs have been allocated.

Possibly due to differing mental images of hierarchical domains, the
names used for the irq_data variables make these functions much harder
to understand than what they need to be.

Rename the struct irq_data pointer to the data embedded in the
descriptor as simply 'irq_data' and refer to the data allocated by this
interface as 'parent_irq_data' so that the names reflect how
hierarchical domains are implemented.

Reviewed-by: default avatarPhilippe Mathieu-Daudé <philmd@linaro.org>
Tested-by: default avatarHsin-Yi Wang <hsinyi@chromium.org>
Tested-by: default avatarMark-PK Tsai <mark-pk.tsai@mediatek.com>
Signed-off-by: default avatarJohan Hovold <johan+linaro@kernel.org>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20230213104302.17307-12-johan+linaro@kernel.org
parent 4e0d86df
Loading
Loading
Loading
Loading
+32 −33
Original line number Diff line number Diff line
@@ -1598,8 +1598,8 @@ static void irq_domain_fix_revmap(struct irq_data *d)
 */
int irq_domain_push_irq(struct irq_domain *domain, int virq, void *arg)
{
	struct irq_data *child_irq_data;
	struct irq_data *root_irq_data = irq_get_irq_data(virq);
	struct irq_data *irq_data = irq_get_irq_data(virq);
	struct irq_data *parent_irq_data;
	struct irq_desc *desc;
	int rv = 0;

@@ -1624,45 +1624,44 @@ int irq_domain_push_irq(struct irq_domain *domain, int virq, void *arg)
	if (WARN_ON(!irq_domain_is_hierarchy(domain)))
		return -EINVAL;

	if (!root_irq_data)
	if (!irq_data)
		return -EINVAL;

	if (domain->parent != root_irq_data->domain)
	if (domain->parent != irq_data->domain)
		return -EINVAL;

	child_irq_data = kzalloc_node(sizeof(*child_irq_data), GFP_KERNEL,
				      irq_data_get_node(root_irq_data));
	if (!child_irq_data)
	parent_irq_data = kzalloc_node(sizeof(*parent_irq_data), GFP_KERNEL,
				       irq_data_get_node(irq_data));
	if (!parent_irq_data)
		return -ENOMEM;

	mutex_lock(&irq_domain_mutex);

	/* Copy the original irq_data. */
	*child_irq_data = *root_irq_data;
	*parent_irq_data = *irq_data;

	/*
	 * Overwrite the root_irq_data, which is embedded in struct
	 * irq_desc, with values for this domain.
	 * Overwrite the irq_data, which is embedded in struct irq_desc, with
	 * values for this domain.
	 */
	root_irq_data->parent_data = child_irq_data;
	root_irq_data->domain = domain;
	root_irq_data->mask = 0;
	root_irq_data->hwirq = 0;
	root_irq_data->chip = NULL;
	root_irq_data->chip_data = NULL;
	irq_data->parent_data = parent_irq_data;
	irq_data->domain = domain;
	irq_data->mask = 0;
	irq_data->hwirq = 0;
	irq_data->chip = NULL;
	irq_data->chip_data = NULL;

	/* May (probably does) set hwirq, chip, etc. */
	rv = irq_domain_alloc_irqs_hierarchy(domain, virq, 1, arg);
	if (rv) {
		/* Restore the original irq_data. */
		*root_irq_data = *child_irq_data;
		kfree(child_irq_data);
		*irq_data = *parent_irq_data;
		kfree(parent_irq_data);
		goto error;
	}

	irq_domain_fix_revmap(child_irq_data);
	irq_domain_set_mapping(domain, root_irq_data->hwirq, root_irq_data);

	irq_domain_fix_revmap(parent_irq_data);
	irq_domain_set_mapping(domain, irq_data->hwirq, irq_data);
error:
	mutex_unlock(&irq_domain_mutex);

@@ -1680,8 +1679,8 @@ EXPORT_SYMBOL_GPL(irq_domain_push_irq);
 */
int irq_domain_pop_irq(struct irq_domain *domain, int virq)
{
	struct irq_data *root_irq_data = irq_get_irq_data(virq);
	struct irq_data *child_irq_data;
	struct irq_data *irq_data = irq_get_irq_data(virq);
	struct irq_data *parent_irq_data;
	struct irq_data *tmp_irq_data;
	struct irq_desc *desc;

@@ -1703,37 +1702,37 @@ int irq_domain_pop_irq(struct irq_domain *domain, int virq)
	if (domain == NULL)
		return -EINVAL;

	if (!root_irq_data)
	if (!irq_data)
		return -EINVAL;

	tmp_irq_data = irq_domain_get_irq_data(domain, virq);

	/* We can only "pop" if this domain is at the top of the list */
	if (WARN_ON(root_irq_data != tmp_irq_data))
	if (WARN_ON(irq_data != tmp_irq_data))
		return -EINVAL;

	if (WARN_ON(root_irq_data->domain != domain))
	if (WARN_ON(irq_data->domain != domain))
		return -EINVAL;

	child_irq_data = root_irq_data->parent_data;
	if (WARN_ON(!child_irq_data))
	parent_irq_data = irq_data->parent_data;
	if (WARN_ON(!parent_irq_data))
		return -EINVAL;

	mutex_lock(&irq_domain_mutex);

	root_irq_data->parent_data = NULL;
	irq_data->parent_data = NULL;

	irq_domain_clear_mapping(domain, root_irq_data->hwirq);
	irq_domain_clear_mapping(domain, irq_data->hwirq);
	irq_domain_free_irqs_hierarchy(domain, virq, 1);

	/* Restore the original irq_data. */
	*root_irq_data = *child_irq_data;
	*irq_data = *parent_irq_data;

	irq_domain_fix_revmap(root_irq_data);
	irq_domain_fix_revmap(irq_data);

	mutex_unlock(&irq_domain_mutex);

	kfree(child_irq_data);
	kfree(parent_irq_data);

	return 0;
}