aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen/events/events_base.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/xen/events/events_base.c')
-rw-r--r--drivers/xen/events/events_base.c47
1 files changed, 32 insertions, 15 deletions
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index 9875d6ec1063..793053065629 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -391,10 +391,10 @@ static void xen_irq_init(unsigned irq)
391 list_add_tail(&info->list, &xen_irq_list_head); 391 list_add_tail(&info->list, &xen_irq_list_head);
392} 392}
393 393
394static int __must_check xen_allocate_irq_dynamic(void) 394static int __must_check xen_allocate_irqs_dynamic(int nvec)
395{ 395{
396 int first = 0; 396 int first = 0;
397 int irq; 397 int i, irq;
398 398
399#ifdef CONFIG_X86_IO_APIC 399#ifdef CONFIG_X86_IO_APIC
400 /* 400 /*
@@ -408,14 +408,22 @@ static int __must_check xen_allocate_irq_dynamic(void)
408 first = get_nr_irqs_gsi(); 408 first = get_nr_irqs_gsi();
409#endif 409#endif
410 410
411 irq = irq_alloc_desc_from(first, -1); 411 irq = irq_alloc_descs_from(first, nvec, -1);
412 412
413 if (irq >= 0) 413 if (irq >= 0) {
414 xen_irq_init(irq); 414 for (i = 0; i < nvec; i++)
415 xen_irq_init(irq + i);
416 }
415 417
416 return irq; 418 return irq;
417} 419}
418 420
421static inline int __must_check xen_allocate_irq_dynamic(void)
422{
423
424 return xen_allocate_irqs_dynamic(1);
425}
426
419static int __must_check xen_allocate_irq_gsi(unsigned gsi) 427static int __must_check xen_allocate_irq_gsi(unsigned gsi)
420{ 428{
421 int irq; 429 int irq;
@@ -738,22 +746,25 @@ int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc)
738} 746}
739 747
740int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, 748int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
741 int pirq, const char *name, domid_t domid) 749 int pirq, int nvec, const char *name, domid_t domid)
742{ 750{
743 int irq, ret; 751 int i, irq, ret;
744 752
745 mutex_lock(&irq_mapping_update_lock); 753 mutex_lock(&irq_mapping_update_lock);
746 754
747 irq = xen_allocate_irq_dynamic(); 755 irq = xen_allocate_irqs_dynamic(nvec);
748 if (irq < 0) 756 if (irq < 0)
749 goto out; 757 goto out;
750 758
751 irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_edge_irq, 759 for (i = 0; i < nvec; i++) {
752 name); 760 irq_set_chip_and_handler_name(irq + i, &xen_pirq_chip, handle_edge_irq, name);
761
762 ret = xen_irq_info_pirq_setup(irq + i, 0, pirq + i, 0, domid,
763 i == 0 ? 0 : PIRQ_MSI_GROUP);
764 if (ret < 0)
765 goto error_irq;
766 }
753 767
754 ret = xen_irq_info_pirq_setup(irq, 0, pirq, 0, domid, 0);
755 if (ret < 0)
756 goto error_irq;
757 ret = irq_set_msi_desc(irq, msidesc); 768 ret = irq_set_msi_desc(irq, msidesc);
758 if (ret < 0) 769 if (ret < 0)
759 goto error_irq; 770 goto error_irq;
@@ -761,7 +772,8 @@ out:
761 mutex_unlock(&irq_mapping_update_lock); 772 mutex_unlock(&irq_mapping_update_lock);
762 return irq; 773 return irq;
763error_irq: 774error_irq:
764 __unbind_from_irq(irq); 775 for (; i >= 0; i--)
776 __unbind_from_irq(irq + i);
765 mutex_unlock(&irq_mapping_update_lock); 777 mutex_unlock(&irq_mapping_update_lock);
766 return ret; 778 return ret;
767} 779}
@@ -780,7 +792,12 @@ int xen_destroy_irq(int irq)
780 if (!desc) 792 if (!desc)
781 goto out; 793 goto out;
782 794
783 if (xen_initial_domain()) { 795 /*
796 * If trying to remove a vector in a MSI group different
797 * than the first one skip the PIRQ unmap unless this vector
798 * is the first one in the group.
799 */
800 if (xen_initial_domain() && !(info->u.pirq.flags & PIRQ_MSI_GROUP)) {
784 unmap_irq.pirq = info->u.pirq.pirq; 801 unmap_irq.pirq = info->u.pirq.pirq;
785 unmap_irq.domid = info->u.pirq.domid; 802 unmap_irq.domid = info->u.pirq.domid;
786 rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq); 803 rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq);