.retrigger      = ioapic_retrigger_irq,
 };
 
-int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev)
+int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 {
        struct msi_msg msg;
-       int ret;
+       int irq, ret;
+       irq = create_irq();
+       if (irq < 0)
+               return irq;
+
+       set_irq_msi(irq, desc);
        ret = msi_compose_msg(dev, irq, &msg);
-       if (ret < 0)
+       if (ret < 0) {
+               destroy_irq(irq);
                return ret;
+       }
 
        write_msi_msg(irq, &msg);
 
        set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq,
                                      "edge");
 
-       return 0;
+       return irq;
 }
 
 void arch_teardown_msi_irq(unsigned int irq)
 {
-       return;
+       destroy_irq(irq);
 }
 
 #endif /* CONFIG_PCI_MSI */
 
 }
 #endif /* CONFIG_SMP */
 
-int ia64_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
+int ia64_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
 {
        struct msi_msg  msg;
        unsigned long   dest_phys_id;
-       unsigned int    vector;
+       unsigned int    irq, vector;
 
+       irq = create_irq();
+       if (irq < 0)
+               return irq;
+
+       set_irq_msi(irq, desc);
        dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map));
        vector = irq;
 
        write_msi_msg(irq, &msg);
        set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq);
 
-       return 0;
+       return irq;
 }
 
 void ia64_teardown_msi_irq(unsigned int irq)
 {
-       return;         /* no-op */
+       destroy_irq(irq);
 }
 
 static void ia64_ack_msi_irq(unsigned int irq)
 };
 
 
-int arch_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
+int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
 {
        if (platform_setup_msi_irq)
-               return platform_setup_msi_irq(irq, pdev);
+               return platform_setup_msi_irq(pdev, desc);
 
-       return ia64_setup_msi_irq(irq, pdev);
+       return ia64_setup_msi_irq(pdev, desc);
 }
 
 void arch_teardown_msi_irq(unsigned int irq)
 
        sn_intr_free(nasid, widget, sn_irq_info);
        sn_msi_info[irq].sn_irq_info = NULL;
 
-       return;
+       destroy_irq(irq);
 }
 
-int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
+int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry)
 {
        struct msi_msg msg;
-       struct msi_desc *entry;
        int widget;
        int status;
        nasid_t nasid;
        struct sn_irq_info *sn_irq_info;
        struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev);
        struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
+       int irq;
 
-       entry = get_irq_msi(irq);
        if (!entry->msi_attrib.is_64)
                return -EINVAL;
 
        if (provider == NULL || provider->dma_map_consistent == NULL)
                return -EINVAL;
 
+       irq = create_irq();
+       if (irq < 0)
+               return irq;
+
+       set_irq_msi(irq, entry);
        /*
         * Set up the vector plumbing.  Let the prom (via sn_intr_alloc)
         * decide which cpu to direct this msi at by default.
                        SWIN_WIDGETNUM(bussoft->bs_base);
 
        sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
-       if (! sn_irq_info)
+       if (! sn_irq_info) {
+               destroy_irq(irq);
                return -ENOMEM;
+       }
 
        status = sn_intr_alloc(nasid, widget, sn_irq_info, irq, -1, -1);
        if (status) {
                kfree(sn_irq_info);
+               destroy_irq(irq);
                return -ENOMEM;
        }
 
        if (! bus_addr) {
                sn_intr_free(nasid, widget, sn_irq_info);
                kfree(sn_irq_info);
+               destroy_irq(irq);
                return -ENOMEM;
        }
 
        write_msi_msg(irq, &msg);
        set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq);
 
-       return 0;
+       return irq;
 }
 
 #ifdef CONFIG_SMP
 
        .retrigger      = ioapic_retrigger_irq,
 };
 
-int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev)
+int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 {
        struct msi_msg msg;
-       int ret;
+       int irq, ret;
+       irq = create_irq();
+       if (irq < 0)
+               return irq;
+
+       set_irq_msi(irq, desc);
        ret = msi_compose_msg(dev, irq, &msg);
-       if (ret < 0)
+       if (ret < 0) {
+               destroy_irq(irq);
                return ret;
+       }
 
        write_msi_msg(irq, &msg);
 
        set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
 
-       return 0;
+       return irq;
 }
 
 void arch_teardown_msi_irq(unsigned int irq)
 {
-       return;
+       destroy_irq(irq);
 }
 
 #endif /* CONFIG_PCI_MSI */
 
        return entry;
 }
 
-static int create_msi_irq(void)
-{
-       struct msi_desc *entry;
-       int irq;
-
-       entry = alloc_msi_entry();
-       if (!entry)
-               return -ENOMEM;
-
-       irq = create_irq();
-       if (irq < 0) {
-               kmem_cache_free(msi_cachep, entry);
-               return -EBUSY;
-       }
-
-       set_irq_msi(irq, entry);
-
-       return irq;
-}
-
-static void destroy_msi_irq(unsigned int irq)
-{
-       struct msi_desc *entry;
-
-       entry = get_irq_msi(irq);
-       set_irq_chip(irq, NULL);
-       set_irq_msi(irq, NULL);
-       destroy_irq(irq);
-       kmem_cache_free(msi_cachep, entry);
-}
-
 static void enable_msi_mode(struct pci_dev *dev, int pos, int type)
 {
        u16 control;
  **/
 static int msi_capability_init(struct pci_dev *dev)
 {
-       int status;
        struct msi_desc *entry;
        int pos, irq;
        u16 control;
        pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
        pci_read_config_word(dev, msi_control_reg(pos), &control);
        /* MSI Entry Initialization */
-       irq = create_msi_irq();
-       if (irq < 0)
-               return irq;
+       entry = alloc_msi_entry();
+       if (!entry)
+               return -ENOMEM;
 
-       entry = get_irq_msi(irq);
-       entry->link.head = irq;
-       entry->link.tail = irq;
        entry->msi_attrib.type = PCI_CAP_ID_MSI;
        entry->msi_attrib.is_64 = is_64bit_address(control);
        entry->msi_attrib.entry_nr = 0;
                        maskbits);
        }
        /* Configure MSI capability structure */
-       status = arch_setup_msi_irq(irq, dev);
-       if (status < 0) {
-               destroy_msi_irq(irq);
-               return status;
+       irq = arch_setup_msi_irq(dev, entry);
+       if (irq < 0) {
+               kmem_cache_free(msi_cachep, entry);
+               return irq;
        }
-
+       entry->link.head = irq;
+       entry->link.tail = irq;
        dev->first_msi_irq = irq;
        set_irq_msi(irq, entry);
+
        /* Set MSI enabled bits  */
        enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
 
                                struct msix_entry *entries, int nvec)
 {
        struct msi_desc *head = NULL, *tail = NULL, *entry = NULL;
-       int status;
        int irq, pos, i, j, nr_entries, temp = 0;
        unsigned long phys_addr;
        u32 table_offset;
 
        /* MSI-X Table Initialization */
        for (i = 0; i < nvec; i++) {
-               irq = create_msi_irq();
-               if (irq < 0)
+               entry = alloc_msi_entry();
+               if (!entry)
                        break;
 
-               entry = get_irq_msi(irq);
                j = entries[i].entry;
-               entries[i].vector = irq;
                entry->msi_attrib.type = PCI_CAP_ID_MSIX;
                entry->msi_attrib.is_64 = 1;
                entry->msi_attrib.entry_nr = j;
                entry->msi_attrib.pos = pos;
                entry->dev = dev;
                entry->mask_base = base;
+
+               /* Configure MSI-X capability structure */
+               irq = arch_setup_msi_irq(dev, entry);
+               if (irq < 0) {
+                       kmem_cache_free(msi_cachep, entry);
+                       break;
+               }
+               entries[i].vector = irq;
                if (!head) {
                        entry->link.head = irq;
                        entry->link.tail = irq;
                }
                temp = irq;
                tail = entry;
-               /* Configure MSI-X capability structure */
-               status = arch_setup_msi_irq(irq, dev);
-               if (status < 0) {
-                       destroy_msi_irq(irq);
-                       break;
-               }
 
                set_irq_msi(irq, entry);
        }
        int head, entry_nr, type;
        void __iomem *base;
 
-       arch_teardown_msi_irq(irq);
-
        entry = get_irq_msi(irq);
        if (!entry || entry->dev != dev) {
                return -EINVAL;
        base = entry->mask_base;
        get_irq_msi(entry->link.head)->link.tail = entry->link.tail;
        get_irq_msi(entry->link.tail)->link.head = entry->link.head;
-       entry->dev = NULL;
 
-       destroy_msi_irq(irq);
+       arch_teardown_msi_irq(irq);
+       kmem_cache_free(msi_cachep, entry);
 
        if (type == PCI_CAP_ID_MSIX) {
                writel(1, base + entry_nr * PCI_MSIX_ENTRY_SIZE +
 
 struct pci_bus;
 struct task_struct;
 struct pci_dev;
+struct msi_desc;
 
 typedef void ia64_mv_setup_t (char **);
 typedef void ia64_mv_cpu_init_t (void);
 typedef unsigned int ia64_mv_readl_relaxed_t (const volatile void __iomem *);
 typedef unsigned long ia64_mv_readq_relaxed_t (const volatile void __iomem *);
 
-typedef int ia64_mv_setup_msi_irq_t (unsigned int irq, struct pci_dev *pdev);
+typedef int ia64_mv_setup_msi_irq_t (struct pci_dev *pdev, struct msi_desc *);
 typedef void ia64_mv_teardown_msi_irq_t (unsigned int irq);
 
 static inline void
 
 /*
  * The arch hook for setup up msi irqs
  */
-int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev);
+int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
 void arch_teardown_msi_irq(unsigned int irq);