aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen
diff options
context:
space:
mode:
authorRoger Pau Monne <roger.pau@citrix.com>2014-02-27 13:15:35 -0500
committerDavid Vrabel <david.vrabel@citrix.com>2014-03-18 10:40:09 -0400
commit4892c9b4ada9f9a71a0da7a268f95e988d88064b (patch)
tree57c9f627ab44ebec2a948dc11ca69cb0011607de /drivers/xen
parentefdfa3eda5d7b33c6e3c4f6e66144fcd10ed41a3 (diff)
xen: add support for MSI message groups
Add support for MSI message groups for Xen Dom0 using the MAP_PIRQ_TYPE_MULTI_MSI pirq map type. In order to keep track of which pirq is the first one in the group all pirqs in the MSI group except for the first one have the newly introduced PIRQ_MSI_GROUP flag set. This prevents calling PHYSDEVOP_unmap_pirq on them, since the unmap must be done with the first pirq in the group. Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> Signed-off-by: David Vrabel <david.vrabel@citrix.com> Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Diffstat (limited to 'drivers/xen')
-rw-r--r--drivers/xen/events/events_base.c47
-rw-r--r--drivers/xen/events/events_internal.h1
2 files changed, 33 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);
diff --git a/drivers/xen/events/events_internal.h b/drivers/xen/events/events_internal.h
index 677f41a0fff9..50c2050a1e32 100644
--- a/drivers/xen/events/events_internal.h
+++ b/drivers/xen/events/events_internal.h
@@ -53,6 +53,7 @@ struct irq_info {
53 53
54#define PIRQ_NEEDS_EOI (1 << 0) 54#define PIRQ_NEEDS_EOI (1 << 0)
55#define PIRQ_SHAREABLE (1 << 1) 55#define PIRQ_SHAREABLE (1 << 1)
56#define PIRQ_MSI_GROUP (1 << 2)
56 57
57struct evtchn_ops { 58struct evtchn_ops {
58 unsigned (*max_channels)(void); 59 unsigned (*max_channels)(void);