return allocated ? allocated : -ENOSPC;
 }
 
+#define VIRQ_CAN_RESERVE       0x01
+#define VIRQ_ACTIVATE          0x02
+#define VIRQ_NOMASK_QUIRK      0x04
+
+static int msi_init_virq(struct irq_domain *domain, int virq, unsigned int vflags)
+{
+       struct irq_data *irqd = irq_domain_get_irq_data(domain, virq);
+       int ret;
+
+       if (!(vflags & VIRQ_CAN_RESERVE)) {
+               irqd_clr_can_reserve(irqd);
+               if (vflags & VIRQ_NOMASK_QUIRK)
+                       irqd_set_msi_nomask_quirk(irqd);
+       }
+
+       if (!(vflags & VIRQ_ACTIVATE))
+               return 0;
+
+       ret = irq_domain_activate_irq(irqd, vflags & VIRQ_CAN_RESERVE);
+       if (ret)
+               return ret;
+       /*
+        * If the interrupt uses reservation mode, clear the activated bit
+        * so request_irq() will assign the final vector.
+        */
+       if (vflags & VIRQ_CAN_RESERVE)
+               irqd_clr_activated(irqd);
+       return 0;
+}
+
 int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
                            int nvec)
 {
        struct msi_domain_info *info = domain->host_data;
        struct msi_domain_ops *ops = info->ops;
-       struct irq_data *irq_data;
-       struct msi_desc *desc;
        msi_alloc_info_t arg = { };
+       unsigned int vflags = 0;
+       struct msi_desc *desc;
        int allocated = 0;
        int i, ret, virq;
-       bool can_reserve;
 
        ret = msi_domain_prepare_irqs(domain, dev, nvec, &arg);
        if (ret)
                return ret;
 
-       for_each_msi_entry(desc, dev) {
+       /*
+        * This flag is set by the PCI layer as we need to activate
+        * the MSI entries before the PCI layer enables MSI in the
+        * card. Otherwise the card latches a random msi message.
+        */
+       if (info->flags & MSI_FLAG_ACTIVATE_EARLY)
+               vflags |= VIRQ_ACTIVATE;
+
+       /*
+        * Interrupt can use a reserved vector and will not occupy
+        * a real device vector until the interrupt is requested.
+        */
+       if (msi_check_reservation_mode(domain, info, dev)) {
+               vflags |= VIRQ_CAN_RESERVE;
+               /*
+                * MSI affinity setting requires a special quirk (X86) when
+                * reservation mode is active.
+                */
+               if (domain->flags & IRQ_DOMAIN_MSI_NOMASK_QUIRK)
+                       vflags |= VIRQ_NOMASK_QUIRK;
+       }
+
+       msi_for_each_desc(desc, dev, MSI_DESC_NOTASSOCIATED) {
                ops->set_desc(&arg, desc);
 
                virq = __irq_domain_alloc_irqs(domain, -1, desc->nvec_used,
                for (i = 0; i < desc->nvec_used; i++) {
                        irq_set_msi_desc_off(virq, i, desc);
                        irq_debugfs_copy_devname(virq + i, dev);
+                       ret = msi_init_virq(domain, virq + i, vflags);
+                       if (ret)
+                               return ret;
                }
                allocated++;
        }
-
-       can_reserve = msi_check_reservation_mode(domain, info, dev);
-
-       /*
-        * This flag is set by the PCI layer as we need to activate
-        * the MSI entries before the PCI layer enables MSI in the
-        * card. Otherwise the card latches a random msi message.
-        */
-       if (!(info->flags & MSI_FLAG_ACTIVATE_EARLY))
-               goto skip_activate;
-
-       for_each_msi_vector(desc, i, dev) {
-               if (desc->irq == i) {
-                       virq = desc->irq;
-                       dev_dbg(dev, "irq [%d-%d] for MSI\n",
-                               virq, virq + desc->nvec_used - 1);
-               }
-
-               irq_data = irq_domain_get_irq_data(domain, i);
-               if (!can_reserve) {
-                       irqd_clr_can_reserve(irq_data);
-                       if (domain->flags & IRQ_DOMAIN_MSI_NOMASK_QUIRK)
-                               irqd_set_msi_nomask_quirk(irq_data);
-               }
-               ret = irq_domain_activate_irq(irq_data, can_reserve);
-               if (ret)
-                       return ret;
-       }
-
-skip_activate:
-       /*
-        * If these interrupts use reservation mode, clear the activated bit
-        * so request_irq() will assign the final vector.
-        */
-       if (can_reserve) {
-               for_each_msi_vector(desc, i, dev) {
-                       irq_data = irq_domain_get_irq_data(domain, i);
-                       irqd_clr_activated(irq_data);
-               }
-       }
        return 0;
 }
 
 
 void __msi_domain_free_irqs(struct irq_domain *domain, struct device *dev)
 {
-       struct irq_data *irq_data;
+       struct irq_data *irqd;
        struct msi_desc *desc;
        int i;
 
-       for_each_msi_vector(desc, i, dev) {
-               irq_data = irq_domain_get_irq_data(domain, i);
-               if (irqd_is_activated(irq_data))
-                       irq_domain_deactivate_irq(irq_data);
-       }
-
-       for_each_msi_entry(desc, dev) {
-               /*
-                * We might have failed to allocate an MSI early
-                * enough that there is no IRQ associated to this
-                * entry. If that's the case, don't do anything.
-                */
-               if (desc->irq) {
-                       irq_domain_free_irqs(desc->irq, desc->nvec_used);
-                       desc->irq = 0;
+       /* Only handle MSI entries which have an interrupt associated */
+       msi_for_each_desc(desc, dev, MSI_DESC_ASSOCIATED) {
+               /* Make sure all interrupts are deactivated */
+               for (i = 0; i < desc->nvec_used; i++) {
+                       irqd = irq_domain_get_irq_data(domain, desc->irq + i);
+                       if (irqd && irqd_is_activated(irqd))
+                               irq_domain_deactivate_irq(irqd);
                }
+
+               irq_domain_free_irqs(desc->irq, desc->nvec_used);
+               desc->irq = 0;
        }
 }