These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / sh / intc / virq.c
index f30ac93..e789962 100644 (file)
@@ -83,12 +83,11 @@ EXPORT_SYMBOL_GPL(intc_irq_lookup);
 
 static int add_virq_to_pirq(unsigned int irq, unsigned int virq)
 {
-       struct intc_virq_list **last, *entry;
-       struct irq_data *data = irq_get_irq_data(irq);
+       struct intc_virq_list *entry;
+       struct intc_virq_list **last = NULL;
 
        /* scan for duplicates */
-       last = (struct intc_virq_list **)&data->handler_data;
-       for_each_virq(entry, data->handler_data) {
+       for_each_virq(entry, irq_get_handler_data(irq)) {
                if (entry->irq == virq)
                        return 0;
                last = &entry->next;
@@ -102,14 +101,18 @@ static int add_virq_to_pirq(unsigned int irq, unsigned int virq)
 
        entry->irq = virq;
 
-       *last = entry;
+       if (last)
+               *last = entry;
+       else
+               irq_set_handler_data(irq, entry);
 
        return 0;
 }
 
-static void intc_virq_handler(unsigned int irq, struct irq_desc *desc)
+static void intc_virq_handler(struct irq_desc *desc)
 {
-       struct irq_data *data = irq_get_irq_data(irq);
+       unsigned int irq = irq_desc_get_irq(desc);
+       struct irq_data *data = irq_desc_get_irq_data(desc);
        struct irq_chip *chip = irq_data_get_irq_chip(data);
        struct intc_virq_list *entry, *vlist = irq_data_get_irq_handler_data(data);
        struct intc_desc_int *d = get_intc_desc(irq);
@@ -118,12 +121,14 @@ static void intc_virq_handler(unsigned int irq, struct irq_desc *desc)
 
        for_each_virq(entry, vlist) {
                unsigned long addr, handle;
+               struct irq_desc *vdesc = irq_to_desc(entry->irq);
 
-               handle = (unsigned long)irq_get_handler_data(entry->irq);
-               addr = INTC_REG(d, _INTC_ADDR_E(handle), 0);
-
-               if (intc_reg_fns[_INTC_FN(handle)](addr, handle, 0))
-                       generic_handle_irq(entry->irq);
+               if (vdesc) {
+                       handle = (unsigned long)irq_desc_get_handler_data(vdesc);
+                       addr = INTC_REG(d, _INTC_ADDR_E(handle), 0);
+                       if (intc_reg_fns[_INTC_FN(handle)](addr, handle, 0))
+                               generic_handle_irq_desc(vdesc);
+               }
        }
 
        chip->irq_unmask(data);
@@ -243,8 +248,9 @@ restart:
                 */
                irq_set_nothread(irq);
 
-               irq_set_chained_handler(entry->pirq, intc_virq_handler);
+               /* Set handler data before installing the handler */
                add_virq_to_pirq(entry->pirq, irq);
+               irq_set_chained_handler(entry->pirq, intc_virq_handler);
 
                radix_tree_tag_clear(&d->tree, entry->enum_id,
                                     INTC_TAG_VIRQ_NEEDS_ALLOC);