* Revmap data, used internally by irq_domain
  * @revmap_size: Size of the linear map table @revmap[]
  * @revmap_tree: Radix map tree for hwirqs that don't fit in the linear map
+ * @revmap_mutex: Lock for the revmap
  * @revmap: Linear table of irq_data pointers
  */
 struct irq_domain {
        irq_hw_number_t hwirq_max;
        unsigned int revmap_size;
        struct radix_tree_root revmap_tree;
-       struct mutex revmap_tree_mutex;
-       struct irq_data *revmap[];
+       struct mutex revmap_mutex;
+       struct irq_data __rcu *revmap[];
 };
 
 /* Irq domain flags */
 
 
        /* Fill structure */
        INIT_RADIX_TREE(&domain->revmap_tree, GFP_KERNEL);
-       mutex_init(&domain->revmap_tree_mutex);
+       mutex_init(&domain->revmap_mutex);
        domain->ops = ops;
        domain->host_data = host_data;
        domain->hwirq_max = hwirq_max;
        if (irq_domain_is_nomap(domain))
                return;
 
-       if (hwirq < domain->revmap_size) {
-               domain->revmap[hwirq] = NULL;
-       } else {
-               mutex_lock(&domain->revmap_tree_mutex);
+       mutex_lock(&domain->revmap_mutex);
+       if (hwirq < domain->revmap_size)
+               rcu_assign_pointer(domain->revmap[hwirq], NULL);
+       else
                radix_tree_delete(&domain->revmap_tree, hwirq);
-               mutex_unlock(&domain->revmap_tree_mutex);
-       }
+       mutex_unlock(&domain->revmap_mutex);
 }
 
 static void irq_domain_set_mapping(struct irq_domain *domain,
        if (irq_domain_is_nomap(domain))
                return;
 
-       if (hwirq < domain->revmap_size) {
-               domain->revmap[hwirq] = irq_data;
-       } else {
-               mutex_lock(&domain->revmap_tree_mutex);
+       mutex_lock(&domain->revmap_mutex);
+       if (hwirq < domain->revmap_size)
+               rcu_assign_pointer(domain->revmap[hwirq], irq_data);
+       else
                radix_tree_insert(&domain->revmap_tree, hwirq, irq_data);
-               mutex_unlock(&domain->revmap_tree_mutex);
-       }
+       mutex_unlock(&domain->revmap_mutex);
 }
 
 static void irq_domain_disassociate(struct irq_domain *domain, unsigned int irq)
                return 0;
        }
 
+       rcu_read_lock();
        /* Check if the hwirq is in the linear revmap. */
        if (hwirq < domain->revmap_size)
-               return domain->revmap[hwirq]->irq;
-
-       rcu_read_lock();
-       data = radix_tree_lookup(&domain->revmap_tree, hwirq);
+               data = rcu_dereference(domain->revmap[hwirq]);
+       else
+               data = radix_tree_lookup(&domain->revmap_tree, hwirq);
        rcu_read_unlock();
        return data ? data->irq : 0;
 }
        if (irq_domain_is_nomap(d->domain))
                return;
 
+       /* Fix up the revmap. */
+       mutex_lock(&d->domain->revmap_mutex);
        if (d->hwirq < d->domain->revmap_size) {
                /* Not using radix tree */
-               d->domain->revmap[d->hwirq] = d;
-               return;
+               rcu_assign_pointer(d->domain->revmap[d->hwirq], d);
+       } else {
+               slot = radix_tree_lookup_slot(&d->domain->revmap_tree, d->hwirq);
+               if (slot)
+                       radix_tree_replace_slot(&d->domain->revmap_tree, slot, d);
        }
-
-       /* Fix up the revmap. */
-       mutex_lock(&d->domain->revmap_tree_mutex);
-       slot = radix_tree_lookup_slot(&d->domain->revmap_tree, d->hwirq);
-       if (slot)
-               radix_tree_replace_slot(&d->domain->revmap_tree, slot, d);
-       mutex_unlock(&d->domain->revmap_tree_mutex);
+       mutex_unlock(&d->domain->revmap_mutex);
 }
 
 /**