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 Original line 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)
int irq_domain_push_irq(struct irq_domain *domain, int virq, void *arg)
{
{
	struct irq_data *child_irq_data;
	struct irq_data *irq_data = irq_get_irq_data(virq);
	struct irq_data *root_irq_data = irq_get_irq_data(virq);
	struct irq_data *parent_irq_data;
	struct irq_desc *desc;
	struct irq_desc *desc;
	int rv = 0;
	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)))
	if (WARN_ON(!irq_domain_is_hierarchy(domain)))
		return -EINVAL;
		return -EINVAL;


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


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


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


	mutex_lock(&irq_domain_mutex);
	mutex_lock(&irq_domain_mutex);


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


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


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

error:
error:
	mutex_unlock(&irq_domain_mutex);
	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)
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 *irq_data = irq_get_irq_data(virq);
	struct irq_data *child_irq_data;
	struct irq_data *parent_irq_data;
	struct irq_data *tmp_irq_data;
	struct irq_data *tmp_irq_data;
	struct irq_desc *desc;
	struct irq_desc *desc;


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


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


	tmp_irq_data = irq_domain_get_irq_data(domain, virq);
	tmp_irq_data = irq_domain_get_irq_data(domain, virq);


	/* We can only "pop" if this domain is at the top of the list */
	/* 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;
		return -EINVAL;


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


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


	mutex_lock(&irq_domain_mutex);
	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);
	irq_domain_free_irqs_hierarchy(domain, virq, 1);


	/* Restore the original irq_data. */
	/* 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);
	mutex_unlock(&irq_domain_mutex);


	kfree(child_irq_data);
	kfree(parent_irq_data);


	return 0;
	return 0;
}
}