Re: [PATCH 01/12] irqdomain: Split disassociating code intoseparate function

From: Benjamin Herrenschmidt
Date: Sat Jun 16 2012 - 01:57:54 EST


On Fri, 2012-06-15 at 23:01 -0600, Grant Likely wrote:
> This patch moves the irq disassociation code out into a separate
> function in preparation to extend irq_setup_virq to handle multiple
> irqs and rename it for use by interrupt controller drivers. The new
> function will be used by irq_setup_virq() in its error path.
>
> Signed-off-by: Grant Likely <grant.likely@xxxxxxxxxxxx>
> Cc: Paul Mundt <lethal@xxxxxxxxxxxx>

Acked-by: Benjamin Herrenschmidt <benh@xxxxxxxxxxxxxxxxxxx>

> Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
> Cc: Rob Herring <rob.herring@xxxxxxxxxxx>
> ---
> kernel/irq/irqdomain.c | 75 ++++++++++++++++++++++++++++++------------------
> 1 file changed, 47 insertions(+), 28 deletions(-)
>
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index b1f774c..4161d2a 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -333,6 +333,52 @@ void irq_set_default_host(struct irq_domain *domain)
> }
> EXPORT_SYMBOL_GPL(irq_set_default_host);
>
> +static void irq_domain_disassociate_many(struct irq_domain *domain,
> + unsigned int irq_base, int count)
> +{
> + /*
> + * disassociate in reverse order;
> + * not strictly necessary, but nice for unwinding
> + */
> + while (count--) {
> + int irq = irq_base + count;
> + struct irq_data *irq_data = irq_get_irq_data(irq);
> + irq_hw_number_t hwirq = irq_data->hwirq;
> +
> + if (WARN_ON(!irq_data || irq_data->domain != domain))
> + continue;
> +
> + irq_set_status_flags(irq, IRQ_NOREQUEST);
> +
> + /* remove chip and handler */
> + irq_set_chip_and_handler(irq, NULL, NULL);
> +
> + /* Make sure it's completed */
> + synchronize_irq(irq);
> +
> + /* Tell the PIC about it */
> + if (domain->ops->unmap)
> + domain->ops->unmap(domain, irq);
> + smp_mb();
> +
> + irq_data->domain = NULL;
> + irq_data->hwirq = 0;
> +
> + /* Clear reverse map */
> + switch(domain->revmap_type) {
> + case IRQ_DOMAIN_MAP_LINEAR:
> + if (hwirq < domain->revmap_data.linear.size)
> + domain->revmap_data.linear.revmap[hwirq] = 0;
> + break;
> + case IRQ_DOMAIN_MAP_TREE:
> + mutex_lock(&revmap_trees_mutex);
> + radix_tree_delete(&domain->revmap_data.tree, hwirq);
> + mutex_unlock(&revmap_trees_mutex);
> + break;
> + }
> + }
> +}
> +
> static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,
> irq_hw_number_t hwirq)
> {
> @@ -513,7 +559,6 @@ void irq_dispose_mapping(unsigned int virq)
> {
> struct irq_data *irq_data = irq_get_irq_data(virq);
> struct irq_domain *domain;
> - irq_hw_number_t hwirq;
>
> if (!virq || !irq_data)
> return;
> @@ -526,33 +571,7 @@ void irq_dispose_mapping(unsigned int virq)
> if (domain->revmap_type == IRQ_DOMAIN_MAP_LEGACY)
> return;
>
> - irq_set_status_flags(virq, IRQ_NOREQUEST);
> -
> - /* remove chip and handler */
> - irq_set_chip_and_handler(virq, NULL, NULL);
> -
> - /* Make sure it's completed */
> - synchronize_irq(virq);
> -
> - /* Tell the PIC about it */
> - if (domain->ops->unmap)
> - domain->ops->unmap(domain, virq);
> - smp_mb();
> -
> - /* Clear reverse map */
> - hwirq = irq_data->hwirq;
> - switch(domain->revmap_type) {
> - case IRQ_DOMAIN_MAP_LINEAR:
> - if (hwirq < domain->revmap_data.linear.size)
> - domain->revmap_data.linear.revmap[hwirq] = 0;
> - break;
> - case IRQ_DOMAIN_MAP_TREE:
> - mutex_lock(&revmap_trees_mutex);
> - radix_tree_delete(&domain->revmap_data.tree, hwirq);
> - mutex_unlock(&revmap_trees_mutex);
> - break;
> - }
> -
> + irq_domain_disassociate_many(domain, virq, 1);
> irq_free_desc(virq);
> }
> EXPORT_SYMBOL_GPL(irq_dispose_mapping);


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/