Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / drivers / irqchip / irq-gic-v3-its.c
index 128ac89..cfb9b4e 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/interrupt.h>
 #include <linux/irqdomain.h>
 #include <linux/list.h>
-#include <linux/list_sort.h>
 #include <linux/log2.h>
 #include <linux/memblock.h>
 #include <linux/mm.h>
@@ -1179,7 +1178,7 @@ static void its_irq_compose_msi_msg(struct irq_data *d, struct msi_msg *msg)
        msg->address_hi         = upper_32_bits(addr);
        msg->data               = its_get_event_id(d);
 
-       iommu_dma_map_msi_msg(d->irq, msg);
+       iommu_dma_compose_msi_msg(irq_data_get_msi_desc(d), msg);
 }
 
 static int its_irq_set_irqchip_state(struct irq_data *d,
@@ -1465,9 +1464,8 @@ static struct lpi_range *mk_lpi_range(u32 base, u32 span)
 {
        struct lpi_range *range;
 
-       range = kzalloc(sizeof(*range), GFP_KERNEL);
+       range = kmalloc(sizeof(*range), GFP_KERNEL);
        if (range) {
-               INIT_LIST_HEAD(&range->entry);
                range->base_id = base;
                range->span = span;
        }
@@ -1475,31 +1473,6 @@ static struct lpi_range *mk_lpi_range(u32 base, u32 span)
        return range;
 }
 
-static int lpi_range_cmp(void *priv, struct list_head *a, struct list_head *b)
-{
-       struct lpi_range *ra, *rb;
-
-       ra = container_of(a, struct lpi_range, entry);
-       rb = container_of(b, struct lpi_range, entry);
-
-       return ra->base_id - rb->base_id;
-}
-
-static void merge_lpi_ranges(void)
-{
-       struct lpi_range *range, *tmp;
-
-       list_for_each_entry_safe(range, tmp, &lpi_range_list, entry) {
-               if (!list_is_last(&range->entry, &lpi_range_list) &&
-                   (tmp->base_id == (range->base_id + range->span))) {
-                       tmp->base_id = range->base_id;
-                       tmp->span += range->span;
-                       list_del(&range->entry);
-                       kfree(range);
-               }
-       }
-}
-
 static int alloc_lpi_range(u32 nr_lpis, u32 *base)
 {
        struct lpi_range *range, *tmp;
@@ -1529,25 +1502,49 @@ static int alloc_lpi_range(u32 nr_lpis, u32 *base)
        return err;
 }
 
+static void merge_lpi_ranges(struct lpi_range *a, struct lpi_range *b)
+{
+       if (&a->entry == &lpi_range_list || &b->entry == &lpi_range_list)
+               return;
+       if (a->base_id + a->span != b->base_id)
+               return;
+       b->base_id = a->base_id;
+       b->span += a->span;
+       list_del(&a->entry);
+       kfree(a);
+}
+
 static int free_lpi_range(u32 base, u32 nr_lpis)
 {
-       struct lpi_range *new;
-       int err = 0;
+       struct lpi_range *new, *old;
+
+       new = mk_lpi_range(base, nr_lpis);
+       if (!new)
+               return -ENOMEM;
 
        mutex_lock(&lpi_range_lock);
 
-       new = mk_lpi_range(base, nr_lpis);
-       if (!new) {
-               err = -ENOMEM;
-               goto out;
+       list_for_each_entry_reverse(old, &lpi_range_list, entry) {
+               if (old->base_id < base)
+                       break;
        }
+       /*
+        * old is the last element with ->base_id smaller than base,
+        * so new goes right after it. If there are no elements with
+        * ->base_id smaller than base, &old->entry ends up pointing
+        * at the head of the list, and inserting new it the start of
+        * the list is the right thing to do in that case as well.
+        */
+       list_add(&new->entry, &old->entry);
+       /*
+        * Now check if we can merge with the preceding and/or
+        * following ranges.
+        */
+       merge_lpi_ranges(old, new);
+       merge_lpi_ranges(new, list_next_entry(new, entry));
 
-       list_add(&new->entry, &lpi_range_list);
-       list_sort(NULL, &lpi_range_list, lpi_range_cmp);
-       merge_lpi_ranges();
-out:
        mutex_unlock(&lpi_range_lock);
-       return err;
+       return 0;
 }
 
 static int __init its_lpi_init(u32 id_bits)
@@ -2487,7 +2484,7 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
        int err = 0;
 
        /*
-        * We ignore "dev" entierely, and rely on the dev_id that has
+        * We ignore "dev" entirely, and rely on the dev_id that has
         * been passed via the scratchpad. This limits this domain's
         * usefulness to upper layers that definitely know that they
         * are built on top of the ITS.
@@ -2566,6 +2563,7 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 {
        msi_alloc_info_t *info = args;
        struct its_device *its_dev = info->scratchpad[0].ptr;
+       struct its_node *its = its_dev->its;
        irq_hw_number_t hwirq;
        int err;
        int i;
@@ -2574,6 +2572,10 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
        if (err)
                return err;
 
+       err = iommu_dma_prepare_msi(info->desc, its->get_msi_base(its_dev));
+       if (err)
+               return err;
+
        for (i = 0; i < nr_irqs; i++) {
                err = its_irq_gic_domain_alloc(domain, virq + i, hwirq + i);
                if (err)