unsigned long irq_flags, const char * devname,
                        void *dev_id)
 {
-       unsigned int irq = irq_create_mapping(NULL, ist, 0);
+       unsigned int irq = irq_create_mapping(NULL, ist);
        
        if (irq == NO_IRQ)
                return -EINVAL;
 
                        irq_map[i].host = host;
                        smp_wmb();
 
-                       /* Clear some flags */
-                       get_irq_desc(i)->status
-                               &= ~(IRQ_NOREQUEST | IRQ_LEVEL);
+                       /* Clear norequest flags */
+                       get_irq_desc(i)->status &= ~IRQ_NOREQUEST;
 
                        /* Legacy flags are left to default at this point,
                         * one can then use irq_create_mapping() to
                         * explicitely change them
                         */
-                       ops->map(host, i, i, 0);
+                       ops->map(host, i, i);
                }
                break;
        case IRQ_HOST_MAP_LINEAR:
 }
 
 unsigned int irq_create_mapping(struct irq_host *host,
-                               irq_hw_number_t hwirq,
-                               unsigned int flags)
+                               irq_hw_number_t hwirq)
 {
        unsigned int virq, hint;
 
-       pr_debug("irq: irq_create_mapping(0x%p, 0x%lx, 0x%x)\n",
-                host, hwirq, flags);
+       pr_debug("irq: irq_create_mapping(0x%p, 0x%lx)\n", host, hwirq);
 
        /* Look for default host if nececssary */
        if (host == NULL)
        virq = irq_find_mapping(host, hwirq);
        if (virq != IRQ_NONE) {
                pr_debug("irq: -> existing mapping on virq %d\n", virq);
-               host->ops->map(host, virq, hwirq, flags);
                return virq;
        }
 
        }
        pr_debug("irq: -> obtained virq %d\n", virq);
 
-       /* Clear some flags */
-       get_irq_desc(virq)->status &= ~(IRQ_NOREQUEST | IRQ_LEVEL);
+       /* Clear IRQ_NOREQUEST flag */
+       get_irq_desc(virq)->status &= ~IRQ_NOREQUEST;
 
        /* map it */
-       if (host->ops->map(host, virq, hwirq, flags)) {
+       smp_wmb();
+       irq_map[virq].hwirq = hwirq;
+       smp_mb();
+       if (host->ops->map(host, virq, hwirq)) {
                pr_debug("irq: -> mapping failed, freeing\n");
                irq_free_virt(virq, 1);
                return NO_IRQ;
        }
-       smp_wmb();
-       irq_map[virq].hwirq = hwirq;
-       smp_mb();
        return virq;
 }
 EXPORT_SYMBOL_GPL(irq_create_mapping);
 {
        struct irq_host *host;
        irq_hw_number_t hwirq;
-       unsigned int flags = IRQ_TYPE_NONE;
+       unsigned int type = IRQ_TYPE_NONE;
+       unsigned int virq;
 
        if (controller == NULL)
                host = irq_default_host;
        else
                host = irq_find_host(controller);
-       if (host == NULL)
+       if (host == NULL) {
+               printk(KERN_WARNING "irq: no irq host found for %s !\n",
+                      controller->full_name);
                return NO_IRQ;
+       }
 
        /* If host has no translation, then we assume interrupt line */
        if (host->ops->xlate == NULL)
                hwirq = intspec[0];
        else {
                if (host->ops->xlate(host, controller, intspec, intsize,
-                                    &hwirq, &flags))
+                                    &hwirq, &type))
                        return NO_IRQ;
        }
 
-       return irq_create_mapping(host, hwirq, flags);
+       /* Create mapping */
+       virq = irq_create_mapping(host, hwirq);
+       if (virq == NO_IRQ)
+               return virq;
+
+       /* Set type if specified and different than the current one */
+       if (type != IRQ_TYPE_NONE &&
+           type != (get_irq_desc(virq)->status & IRQF_TRIGGER_MASK))
+               set_irq_type(virq, type);
+       return virq;
 }
 EXPORT_SYMBOL_GPL(irq_create_of_mapping);
 
 
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/bootmem.h>
+#include <linux/irq.h>
 
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/sections.h>
 #include <asm/pci-bridge.h>
 #include <asm/byteorder.h>
-#include <asm/irq.h>
 #include <asm/uaccess.h>
 #include <asm/machdep.h>
 
 
        DBG("Try to map irq for %s...\n", pci_name(pci_dev));
 
+       /* Try to get a mapping from the device-tree */
        if (of_irq_map_pci(pci_dev, &oirq)) {
-               DBG(" -> failed !\n");
-               return -1;
-       }
+               u8 line, pin;
+
+               /* If that fails, lets fallback to what is in the config
+                * space and map that through the default controller. We
+                * also set the type to level low since that's what PCI
+                * interrupts are. If your platform does differently, then
+                * either provide a proper interrupt tree or don't use this
+                * function.
+                */
+               if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin))
+                       return -1;
+               if (pin == 0)
+                       return -1;
+               if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
+                   line == 0xff) {
+                       return -1;
+               }
+               DBG(" -> no map ! Using irq line %d from PCI config\n", line);
 
-       DBG(" -> got one, spec %d cells (0x%08x...) on %s\n",
-           oirq.size, oirq.specifier[0], oirq.controller->full_name);
+               virq = irq_create_mapping(NULL, line);
+               if (virq != NO_IRQ)
+                       set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
+       } else {
+               DBG(" -> got one, spec %d cells (0x%08x...) on %s\n",
+                   oirq.size, oirq.specifier[0], oirq.controller->full_name);
 
-       virq = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size);
+               virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+                                            oirq.size);
+       }
        if(virq == NO_IRQ) {
                DBG(" -> failed to map !\n");
                return -1;
 
 #include <linux/mm.h>
 #include <linux/list.h>
 #include <linux/syscalls.h>
+#include <linux/irq.h>
 
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
 #include <asm/byteorder.h>
-#include <asm/irq.h>
 #include <asm/machdep.h>
 #include <asm/ppc-pci.h>
 
 
        DBG("Try to map irq for %s...\n", pci_name(pci_dev));
 
+       /* Try to get a mapping from the device-tree */
        if (of_irq_map_pci(pci_dev, &oirq)) {
-               DBG(" -> failed !\n");
-               return -1;
-       }
+               u8 line, pin;
+
+               /* If that fails, lets fallback to what is in the config
+                * space and map that through the default controller. We
+                * also set the type to level low since that's what PCI
+                * interrupts are. If your platform does differently, then
+                * either provide a proper interrupt tree or don't use this
+                * function.
+                */
+               if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin))
+                       return -1;
+               if (pin == 0)
+                       return -1;
+               if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
+                   line == 0xff) {
+                       return -1;
+               }
+               DBG(" -> no map ! Using irq line %d from PCI config\n", line);
 
-       DBG(" -> got one, spec %d cells (0x%08x...) on %s\n",
-           oirq.size, oirq.specifier[0], oirq.controller->full_name);
+               virq = irq_create_mapping(NULL, line);
+               if (virq != NO_IRQ)
+                       set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
+       } else {
+               DBG(" -> got one, spec %d cells (0x%08x...) on %s\n",
+                   oirq.size, oirq.specifier[0], oirq.controller->full_name);
 
-       virq = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size);
+               virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+                                            oirq.size);
+       }
        if(virq == NO_IRQ) {
                DBG(" -> failed to map !\n");
                return -1;
 
                if (iic_hosts[node] == NULL)
                        continue;
                virq = irq_create_mapping(iic_hosts[node],
-                                         iic_ipi_to_irq(ipi), 0);
+                                         iic_ipi_to_irq(ipi));
                if (virq == NO_IRQ) {
                        printk(KERN_ERR
                               "iic: failed to map IPI %s on node %d\n",
 }
 
 static int iic_host_map(struct irq_host *h, unsigned int virq,
-                       irq_hw_number_t hw, unsigned int flags)
+                       irq_hw_number_t hw)
 {
        if (hw < IIC_IRQ_IPI0)
                set_irq_chip_and_handler(virq, &iic_chip, handle_fasteoi_irq);
 
        struct spider_pic *pic = spider_virq_to_pic(virq);
        void __iomem *cfg = spider_get_irq_config(pic, irq_map[virq].hwirq);
 
-       /* We use no locking as we should be covered by the descriptor lock
-        * for access to invidual source configuration registers
-        */
        out_be32(cfg, in_be32(cfg) | 0x30000000u);
 }
 
        struct spider_pic *pic = spider_virq_to_pic(virq);
        void __iomem *cfg = spider_get_irq_config(pic, irq_map[virq].hwirq);
 
-       /* We use no locking as we should be covered by the descriptor lock
-        * for access to invidual source configuration registers
-        */
        out_be32(cfg, in_be32(cfg) & ~0x30000000u);
 }
 
        out_be32(pic->regs + TIR_EDC, 0x100 | (src & 0xf));
 }
 
-static struct irq_chip spider_pic = {
-       .typename = " SPIDER   ",
-       .unmask = spider_unmask_irq,
-       .mask = spider_mask_irq,
-       .ack = spider_ack_irq,
-};
-
-static int spider_host_match(struct irq_host *h, struct device_node *node)
-{
-       struct spider_pic *pic = h->host_data;
-       return node == pic->of_node;
-}
-
-static int spider_host_map(struct irq_host *h, unsigned int virq,
-                       irq_hw_number_t hw, unsigned int flags)
+static int spider_set_irq_type(unsigned int virq, unsigned int type)
 {
-       unsigned int sense = flags & IRQ_TYPE_SENSE_MASK;
-       struct spider_pic *pic = h->host_data;
+       unsigned int sense = type & IRQ_TYPE_SENSE_MASK;
+       struct spider_pic *pic = spider_virq_to_pic(virq);
+       unsigned int hw = irq_map[virq].hwirq;
        void __iomem *cfg = spider_get_irq_config(pic, hw);
-       int level = 0;
+       struct irq_desc *desc = get_irq_desc(virq);
+       u32 old_mask;
        u32 ic;
 
        /* Note that only level high is supported for most interrupts */
                break;
        case IRQ_TYPE_LEVEL_LOW:
                ic = 0x0;
-               level = 1;
                break;
        case IRQ_TYPE_LEVEL_HIGH:
        case IRQ_TYPE_NONE:
                ic = 0x1;
-               level = 1;
                break;
        default:
                return -EINVAL;
        }
 
+       /* Update irq_desc */
+       desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
+       desc->status |= type & IRQ_TYPE_SENSE_MASK;
+       if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
+               desc->status |= IRQ_LEVEL;
+
        /* Configure the source. One gross hack that was there before and
         * that I've kept around is the priority to the BE which I set to
         * be the same as the interrupt source number. I don't know wether
         * that's supposed to make any kind of sense however, we'll have to
         * decide that, but for now, I'm not changing the behaviour.
         */
-       out_be32(cfg, (ic << 24) | (0x7 << 16) | (pic->node_id << 4) | 0xe);
+       old_mask = in_be32(cfg) & 0x30000000u;
+       out_be32(cfg, old_mask | (ic << 24) | (0x7 << 16) |
+                (pic->node_id << 4) | 0xe);
        out_be32(cfg + 4, (0x2 << 16) | (hw & 0xff));
 
-       if (level)
-               get_irq_desc(virq)->status |= IRQ_LEVEL;
+       return 0;
+}
+
+static struct irq_chip spider_pic = {
+       .typename = " SPIDER   ",
+       .unmask = spider_unmask_irq,
+       .mask = spider_mask_irq,
+       .ack = spider_ack_irq,
+       .set_type = spider_set_irq_type,
+};
+
+static int spider_host_match(struct irq_host *h, struct device_node *node)
+{
+       struct spider_pic *pic = h->host_data;
+       return node == pic->of_node;
+}
+
+static int spider_host_map(struct irq_host *h, unsigned int virq,
+                       irq_hw_number_t hw)
+{
        set_irq_chip_and_handler(virq, &spider_pic, handle_level_irq);
+
+       /* Set default irq type */
+       set_irq_type(virq, IRQ_TYPE_NONE);
+
        return 0;
 }
 
        if (iic_host == NULL)
                return NO_IRQ;
        /* Manufacture an IIC interrupt number of class 2 */
-       virq = irq_create_mapping(iic_host, 0x20 | unit, 0);
+       virq = irq_create_mapping(iic_host, 0x20 | unit);
        if (virq == NO_IRQ)
                printk(KERN_ERR "spider_pic: failed to map cascade !");
        return virq;
 
        spu->isrc = isrc = tmp[0];
 
        /* Now map interrupts of all 3 classes */
-       spu->irqs[0] = irq_create_mapping(host, 0x00 | isrc, 0);
-       spu->irqs[1] = irq_create_mapping(host, 0x10 | isrc, 0);
-       spu->irqs[2] = irq_create_mapping(host, 0x20 | isrc, 0);
+       spu->irqs[0] = irq_create_mapping(host, 0x00 | isrc);
+       spu->irqs[1] = irq_create_mapping(host, 0x10 | isrc);
+       spu->irqs[2] = irq_create_mapping(host, 0x20 | isrc);
 
        /* Right now, we only fail if class 2 failed */
        return spu->irqs[2] == NO_IRQ ? -EINVAL : 0;
 
        realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3)
                + function;
 
-       return irq_create_mapping(NULL, realirq, IRQ_TYPE_NONE);
+       return irq_create_mapping(NULL, realirq);
 }
 
 #endif /* CONFIG_PCI */
 }
 
 static int iseries_irq_host_map(struct irq_host *h, unsigned int virq,
-                               irq_hw_number_t hw, unsigned int flags)
+                               irq_hw_number_t hw)
 {
        set_irq_chip_and_handler(virq, &iseries_pic, handle_fasteoi_irq);
 
 
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
+#include <linux/irq.h>
 
 #include <asm/sections.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
 #include <asm/grackle.h>
-#ifdef CONFIG_PPC64
-//#include <asm/iommu.h>
 #include <asm/ppc-pci.h>
-#endif
 
 #undef DEBUG
 
 static struct pci_controller *u3_agp;
 static struct pci_controller *u4_pcie;
 static struct pci_controller *u3_ht;
-#define has_second_ohare 0
 #else
 static int has_second_ohare;
 #endif /* CONFIG_PPC64 */
                /* Read interrupt from the device-tree */
                pci_read_irq_line(dev);
 
+#ifdef CONFIG_PPC32
                /* Fixup interrupt for the modem/ethernet combo controller.
                 * on machines with a second ohare chip.
                 * The number in the device tree (27) is bogus (correct for
                 */
                if (has_second_ohare &&
                    dev->vendor == PCI_VENDOR_ID_DEC &&
-                   dev->device == PCI_DEVICE_ID_DEC_TULIP_PLUS)
-                       dev->irq = irq_create_mapping(NULL, 60, 0);
+                   dev->device == PCI_DEVICE_ID_DEC_TULIP_PLUS) {
+                       dev->irq = irq_create_mapping(NULL, 60);
+                       set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW);
+               }
+#endif /* CONFIG_PPC32 */
        }
 }
 
 
 }
 
 static int pmac_pic_host_map(struct irq_host *h, unsigned int virq,
-                            irq_hw_number_t hw, unsigned int flags)
+                            irq_hw_number_t hw)
 {
        struct irq_desc *desc = get_irq_desc(virq);
        int level;
                               unsigned int *out_flags)
 
 {
+       *out_flags = IRQ_TYPE_NONE;
        *out_hwirq = *intspec;
        return 0;
 }
 
        printk(KERN_INFO "irq: System has %d possible interrupts\n", max_irqs);
 #ifdef CONFIG_XMON
-       setup_irq(irq_create_mapping(NULL, 20, 0), &xmon_action);
+       setup_irq(irq_create_mapping(NULL, 20), &xmon_action);
 #endif
 }
 #endif /* CONFIG_PPC32 */
                flags |= OF_IMAP_OLDWORLD_MAC;
        if (get_property(of_chosen, "linux,bootx", NULL) != NULL)
                flags |= OF_IMAP_NO_PHANDLE;
-       of_irq_map_init(flags);
 #endif /* CONFIG_PPC_32 */
 
+       of_irq_map_init(flags);
+
        /* We first try to detect Apple's new Core99 chipset, since mac-io
         * is quite different on those machines and contains an IBM MPIC2.
         */
 
                for (i = 0; i < opicplen; i++) {
                        if (count > 15)
                                break;
-                       virqs[count] = irq_create_mapping(NULL, *(opicprop++),
-                                                        IRQ_TYPE_NONE);
+                       virqs[count] = irq_create_mapping(NULL, *(opicprop++));
                        if (virqs[count] == NO_IRQ)
                                printk(KERN_ERR "Unable to allocate interrupt "
                                       "number for %s\n", np->full_name);
 
 }
 
 static int xics_host_map_direct(struct irq_host *h, unsigned int virq,
-                               irq_hw_number_t hw, unsigned int flags)
+                               irq_hw_number_t hw)
 {
-       unsigned int sense = flags & IRQ_TYPE_SENSE_MASK;
-
-       pr_debug("xics: map_direct virq %d, hwirq 0x%lx, flags: 0x%x\n",
-                virq, hw, flags);
-
-       if (sense && sense != IRQ_TYPE_LEVEL_LOW)
-               printk(KERN_WARNING "xics: using unsupported sense 0x%x"
-                      " for irq %d (h: 0x%lx)\n", flags, virq, hw);
+       pr_debug("xics: map_direct virq %d, hwirq 0x%lx\n", virq, hw);
 
        get_irq_desc(virq)->status |= IRQ_LEVEL;
        set_irq_chip_and_handler(virq, &xics_pic_direct, handle_fasteoi_irq);
 }
 
 static int xics_host_map_lpar(struct irq_host *h, unsigned int virq,
-                             irq_hw_number_t hw, unsigned int flags)
+                             irq_hw_number_t hw)
 {
-       unsigned int sense = flags & IRQ_TYPE_SENSE_MASK;
-
-       pr_debug("xics: map_lpar virq %d, hwirq 0x%lx, flags: 0x%x\n",
-                virq, hw, flags);
-
-       if (sense && sense != IRQ_TYPE_LEVEL_LOW)
-               printk(KERN_WARNING "xics: using unsupported sense 0x%x"
-                      " for irq %d (h: 0x%lx)\n", flags, virq, hw);
+       pr_debug("xics: map_direct virq %d, hwirq 0x%lx\n", virq, hw);
 
        get_irq_desc(virq)->status |= IRQ_LEVEL;
        set_irq_chip_and_handler(virq, &xics_pic_lpar, handle_fasteoi_irq);
 {
        unsigned int ipi;
 
-       ipi = irq_create_mapping(xics_host, XICS_IPI, 0);
+       ipi = irq_create_mapping(xics_host, XICS_IPI);
        BUG_ON(ipi == NO_IRQ);
 
        /*
 
        xics_set_cpu_priority(cpu, 0);
 
+       /*
+        * Clear IPI
+        */
+       if (firmware_has_feature(FW_FEATURE_LPAR))
+               lpar_qirr_info(cpu, 0xff);
+       else
+               direct_qirr_info(cpu, 0xff);
+
        /*
         * we need to EOI the IPI if we got here from kexec down IPI
         *
                return;
        desc = get_irq_desc(ipi);
        if (desc->chip && desc->chip->eoi)
-               desc->chip->eoi(XICS_IPI);
+               desc->chip->eoi(ipi);
 
        /*
         * Some machines need to have at least one cpu in the GIQ,
 
 }
 
 static int i8259_host_map(struct irq_host *h, unsigned int virq,
-                         irq_hw_number_t hw, unsigned int flags)
+                         irq_hw_number_t hw)
 {
        pr_debug("i8259_host_map(%d, 0x%lx)\n", virq, hw);
 
        if (hw == 2)
                get_irq_desc(virq)->status |= IRQ_NOREQUEST;
 
-       /* We use the level stuff only for now, we might want to
+       /* We use the level handler only for now, we might want to
         * be more cautious here but that works for now
         */
        get_irq_desc(virq)->status |= IRQ_LEVEL;
 
        }
 }
 
+#else /* CONFIG_MPIC_BROKEN_U3 */
+
+static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source)
+{
+       return 0;
+}
+
+static void __init mpic_scan_ht_pics(struct mpic *mpic)
+{
+}
+
 #endif /* CONFIG_MPIC_BROKEN_U3 */
 
 
        unsigned int loops = 100000;
        struct mpic *mpic = mpic_from_irq(irq);
        unsigned int src = mpic_irq_to_hw(irq);
-       unsigned long flags;
 
        DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
 
-       spin_lock_irqsave(&mpic_lock, flags);
        mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
                       mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) &
                       ~MPIC_VECPRI_MASK);
                        break;
                }
        } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);
-       spin_unlock_irqrestore(&mpic_lock, flags);
 }
 
 static void mpic_mask_irq(unsigned int irq)
        unsigned int loops = 100000;
        struct mpic *mpic = mpic_from_irq(irq);
        unsigned int src = mpic_irq_to_hw(irq);
-       unsigned long flags;
 
        DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
 
-       spin_lock_irqsave(&mpic_lock, flags);
        mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
                       mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) |
                       MPIC_VECPRI_MASK);
                        break;
                }
        } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
-       spin_unlock_irqrestore(&mpic_lock, flags);
 }
 
 static void mpic_end_irq(unsigned int irq)
                mpic_ht_end_irq(mpic, src);
        mpic_eoi(mpic);
 }
-
-#endif /* CONFIG_MPIC_BROKEN_U3 */
+#endif /* !CONFIG_MPIC_BROKEN_U3 */
 
 #ifdef CONFIG_SMP
 
                       mpic_physmask(cpus_addr(tmp)[0]));       
 }
 
-static unsigned int mpic_flags_to_vecpri(unsigned int flags, int *level)
+static unsigned int mpic_type_to_vecpri(unsigned int type)
 {
-       unsigned int vecpri;
-
        /* Now convert sense value */
-       switch(flags & IRQ_TYPE_SENSE_MASK) {
+       switch(type & IRQ_TYPE_SENSE_MASK) {
        case IRQ_TYPE_EDGE_RISING:
-               vecpri = MPIC_VECPRI_SENSE_EDGE |
-                       MPIC_VECPRI_POLARITY_POSITIVE;
-               *level = 0;
-               break;
+               return MPIC_VECPRI_SENSE_EDGE | MPIC_VECPRI_POLARITY_POSITIVE;
        case IRQ_TYPE_EDGE_FALLING:
-               vecpri = MPIC_VECPRI_SENSE_EDGE |
-                       MPIC_VECPRI_POLARITY_NEGATIVE;
-               *level = 0;
-               break;
+       case IRQ_TYPE_EDGE_BOTH:
+               return MPIC_VECPRI_SENSE_EDGE | MPIC_VECPRI_POLARITY_NEGATIVE;
        case IRQ_TYPE_LEVEL_HIGH:
-               vecpri = MPIC_VECPRI_SENSE_LEVEL |
-                       MPIC_VECPRI_POLARITY_POSITIVE;
-               *level = 1;
-               break;
+               return MPIC_VECPRI_SENSE_LEVEL | MPIC_VECPRI_POLARITY_POSITIVE;
        case IRQ_TYPE_LEVEL_LOW:
        default:
-               vecpri = MPIC_VECPRI_SENSE_LEVEL |
-                       MPIC_VECPRI_POLARITY_NEGATIVE;
-               *level = 1;
+               return MPIC_VECPRI_SENSE_LEVEL | MPIC_VECPRI_POLARITY_NEGATIVE;
        }
-       return vecpri;
+}
+
+static int mpic_set_irq_type(unsigned int virq, unsigned int flow_type)
+{
+       struct mpic *mpic = mpic_from_irq(virq);
+       unsigned int src = mpic_irq_to_hw(virq);
+       struct irq_desc *desc = get_irq_desc(virq);
+       unsigned int vecpri, vold, vnew;
+
+       pr_debug("mpic: set_irq_type(mpic:@%p,virq:%d,src:%d,type:0x%x)\n",
+                mpic, virq, src, flow_type);
+
+       if (src >= mpic->irq_count)
+               return -EINVAL;
+
+       if (flow_type == IRQ_TYPE_NONE)
+               if (mpic->senses && src < mpic->senses_count)
+                       flow_type = mpic->senses[src];
+       if (flow_type == IRQ_TYPE_NONE)
+               flow_type = IRQ_TYPE_LEVEL_LOW;
+
+       desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
+       desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
+       if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
+               desc->status |= IRQ_LEVEL;
+
+       if (mpic_is_ht_interrupt(mpic, src))
+               vecpri = MPIC_VECPRI_POLARITY_POSITIVE |
+                       MPIC_VECPRI_SENSE_EDGE;
+       else
+               vecpri = mpic_type_to_vecpri(flow_type);
+
+       vold = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI);
+       vnew = vold & ~(MPIC_VECPRI_POLARITY_MASK | MPIC_VECPRI_SENSE_MASK);
+       vnew |= vecpri;
+       if (vold != vnew)
+               mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, vnew);
+
+       return 0;
 }
 
 static struct irq_chip mpic_irq_chip = {
-       .mask   = mpic_mask_irq,
-       .unmask = mpic_unmask_irq,
-       .eoi    = mpic_end_irq,
+       .mask           = mpic_mask_irq,
+       .unmask         = mpic_unmask_irq,
+       .eoi            = mpic_end_irq,
+       .set_type       = mpic_set_irq_type,
 };
 
 #ifdef CONFIG_SMP
 static struct irq_chip mpic_ipi_chip = {
-       .mask   = mpic_mask_ipi,
-       .unmask = mpic_unmask_ipi,
-       .eoi    = mpic_end_ipi,
+       .mask           = mpic_mask_ipi,
+       .unmask         = mpic_unmask_ipi,
+       .eoi            = mpic_end_ipi,
 };
 #endif /* CONFIG_SMP */
 
        .mask           = mpic_mask_irq,
        .unmask         = mpic_unmask_ht_irq,
        .eoi            = mpic_end_ht_irq,
+       .set_type       = mpic_set_irq_type,
 };
 #endif /* CONFIG_MPIC_BROKEN_U3 */
 
 }
 
 static int mpic_host_map(struct irq_host *h, unsigned int virq,
-                        irq_hw_number_t hw, unsigned int flags)
+                        irq_hw_number_t hw)
 {
-       struct irq_desc *desc = get_irq_desc(virq);
-       struct irq_chip *chip;
        struct mpic *mpic = h->host_data;
-       u32 v, vecpri = MPIC_VECPRI_SENSE_LEVEL |
-               MPIC_VECPRI_POLARITY_NEGATIVE;
-       int level;
-       unsigned long iflags;
+       struct irq_chip *chip;
 
-       pr_debug("mpic: map virq %d, hwirq 0x%lx, flags: 0x%x\n",
-                virq, hw, flags);
+       pr_debug("mpic: map virq %d, hwirq 0x%lx\n", virq, hw);
 
        if (hw == MPIC_VEC_SPURRIOUS)
                return -EINVAL;
        if (hw >= mpic->irq_count)
                return -EINVAL;
 
-       /* If no sense provided, check default sense array */
-       if (((flags & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_NONE) &&
-           mpic->senses && hw < mpic->senses_count)
-               flags |= mpic->senses[hw];
-
-       vecpri = mpic_flags_to_vecpri(flags, &level);
-       if (level)
-               desc->status |= IRQ_LEVEL;
+       /* Default chip */
        chip = &mpic->hc_irq;
 
 #ifdef CONFIG_MPIC_BROKEN_U3
        /* Check for HT interrupts, override vecpri */
-       if (mpic_is_ht_interrupt(mpic, hw)) {
-               vecpri &= ~(MPIC_VECPRI_SENSE_MASK |
-                           MPIC_VECPRI_POLARITY_MASK);
-               vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
+       if (mpic_is_ht_interrupt(mpic, hw))
                chip = &mpic->hc_ht_irq;
-       }
-#endif
+#endif /* CONFIG_MPIC_BROKEN_U3 */
 
-       /* Reconfigure irq. We must preserve the mask bit as we can be called
-        * while the interrupt is still active (This may change in the future
-        * but for now, it is the case).
-        */
-       spin_lock_irqsave(&mpic_lock, iflags);
-       v = mpic_irq_read(hw, MPIC_IRQ_VECTOR_PRI);
-       vecpri = (v &
-               ~(MPIC_VECPRI_POLARITY_MASK | MPIC_VECPRI_SENSE_MASK)) |
-               vecpri;
-       if (vecpri != v)
-               mpic_irq_write(hw, MPIC_IRQ_VECTOR_PRI, vecpri);
-       spin_unlock_irqrestore(&mpic_lock, iflags);
-
-       pr_debug("mpic: mapping as IRQ, vecpri = 0x%08x (was 0x%08x)\n",
-                vecpri, v);
+       pr_debug("mpic: mapping to irq chip @%p\n", chip);
 
        set_irq_chip_data(virq, mpic);
        set_irq_chip_and_handler(virq, chip, handle_fasteoi_irq);
+
+       /* Set default irq type */
+       set_irq_type(virq, IRQ_TYPE_NONE);
+
        return 0;
 }
 
        if (mpic->irq_count == 0)
                mpic->irq_count = mpic->num_sources;
 
-#ifdef CONFIG_MPIC_BROKEN_U3
        /* Do the HT PIC fixups on U3 broken mpic */
        DBG("MPIC flags: %x\n", mpic->flags);
        if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY))
                mpic_scan_ht_pics(mpic);
-#endif /* CONFIG_MPIC_BROKEN_U3 */
 
        for (i = 0; i < mpic->num_sources; i++) {
                /* start with vector = source number, and masked */
-               u32 vecpri = MPIC_VECPRI_MASK | i | (8 << MPIC_VECPRI_PRIORITY_SHIFT);
-               int level = 1;
+               u32 vecpri = MPIC_VECPRI_MASK | i |
+                       (8 << MPIC_VECPRI_PRIORITY_SHIFT);
                
-               /* do senses munging */
-               if (mpic->senses && i < mpic->senses_count)
-                       vecpri |= mpic_flags_to_vecpri(mpic->senses[i],
-                                                      &level);
-               else
-                       vecpri |= MPIC_VECPRI_SENSE_LEVEL;
-
-               /* deal with broken U3 */
-               if (mpic->flags & MPIC_BROKEN_U3) {
-#ifdef CONFIG_MPIC_BROKEN_U3
-                       if (mpic_is_ht_interrupt(mpic, i)) {
-                               vecpri &= ~(MPIC_VECPRI_SENSE_MASK |
-                                           MPIC_VECPRI_POLARITY_MASK);
-                               vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
-                       }
-#else
-                       printk(KERN_ERR "mpic: BROKEN_U3 set, but CONFIG doesn't match\n");
-#endif
-               }
-
-               DBG("setup source %d, vecpri: %08x, level: %d\n", i, vecpri,
-                   (level != 0));
-
                /* init hw */
                mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri);
                mpic_irq_write(i, MPIC_IRQ_DESTINATION,
 
        for (i = 0; i < 4; i++) {
                unsigned int vipi = irq_create_mapping(mpic->irqhost,
-                                                      MPIC_VEC_IPI_0 + i, 0);
+                                                      MPIC_VEC_IPI_0 + i);
                if (vipi == NO_IRQ) {
                        printk(KERN_ERR "Failed to map IPI %d\n", i);
                        break;
 
                hp->inbuf_end = hp->inbuf;
                hp->state = HVSI_CLOSED;
                hp->vtermno = *vtermno;
-               hp->virq = irq_create_mapping(NULL, irq[0], 0);
+               hp->virq = irq_create_mapping(NULL, irq[0]);
                if (hp->virq == NO_IRQ) {
                        printk(KERN_ERR "%s: couldn't create irq mapping for 0x%x\n",
                                __FUNCTION__, irq[0]);
 
 {
        unsigned int irq;
 
-       irq = irq_create_mapping(NULL, line, 0);
+       irq = irq_create_mapping(NULL, line);
        if (irq != NO_IRQ) {
                dev->interrupt[index].start = irq;
                dev->interrupt[index].flags = IORESOURCE_IRQ;
 
        int (*match)(struct irq_host *h, struct device_node *node);
 
        /* Create or update a mapping between a virtual irq number and a hw
-        * irq number. This can be called several times for the same mapping
-        * but with different flags, though unmap shall always be called
-        * before the virq->hw mapping is changed.
+        * irq number. This is called only once for a given mapping.
         */
-       int (*map)(struct irq_host *h, unsigned int virq,
-                  irq_hw_number_t hw, unsigned int flags);
+       int (*map)(struct irq_host *h, unsigned int virq, irq_hw_number_t hw);
 
        /* Dispose of such a mapping */
        void (*unmap)(struct irq_host *h, unsigned int virq);
 
        /* Translate device-tree interrupt specifier from raw format coming
         * from the firmware to a irq_hw_number_t (interrupt line number) and
-        * trigger flags that can be passed to irq_create_mapping().
-        * If no translation is provided, raw format is assumed to be one cell
-        * for interrupt line and default sense.
+        * type (sense) that can be passed to set_irq_type(). In the absence
+        * of this callback, irq_create_of_mapping() and irq_of_parse_and_map()
+        * will return the hw number in the first cell and IRQ_TYPE_NONE for
+        * the type (which amount to keeping whatever default value the
+        * interrupt controller has for that line)
         */
        int (*xlate)(struct irq_host *h, struct device_node *ctrler,
                     u32 *intspec, unsigned int intsize,
-                    irq_hw_number_t *out_hwirq, unsigned int *out_flags);
+                    irq_hw_number_t *out_hwirq, unsigned int *out_type);
 };
 
 struct irq_host {
  * irq_create_mapping - Map a hardware interrupt into linux virq space
  * @host: host owning this hardware interrupt or NULL for default host
  * @hwirq: hardware irq number in that host space
- * @flags: flags passed to the controller. contains the trigger type among
- *         others. Use IRQ_TYPE_* defined in include/linux/irq.h
  *
  * Only one mapping per hardware interrupt is permitted. Returns a linux
- * virq number. The flags can be used to provide sense information to the
- * controller (typically extracted from the device-tree). If no information
- * is passed, the controller defaults will apply (for example, xics can only
- * do edge so flags are irrelevant for some pseries specific irqs).
- *
- * The device-tree generally contains the trigger info in an encoding that is
- * specific to a given type of controller. In that case, you can directly use
- * host->ops->trigger_xlate() to translate that.
- *
- * It is recommended that new PICs that don't have existing OF bindings chose
- * to use a representation of triggers identical to linux.
+ * virq number.
+ * If the sense/trigger is to be specified, set_irq_type() should be called
+ * on the number returned from that call.
  */
 extern unsigned int irq_create_mapping(struct irq_host *host,
-                                      irq_hw_number_t hwirq,
-                                      unsigned int flags);
+                                      irq_hw_number_t hwirq);
 
 
 /***
  *
  * This function is identical to irq_create_mapping except that it takes
  * as input informations straight from the device-tree (typically the results
- * of the of_irq_map_*() functions
+ * of the of_irq_map_*() functions.
  */
 extern unsigned int irq_create_of_mapping(struct device_node *controller,
                                          u32 *intspec, unsigned int intsize);