aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen/events.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/xen/events.c')
-rw-r--r--drivers/xen/events.c39
1 files changed, 34 insertions, 5 deletions
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 0ae1d4d7e18c..3ff822b48145 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -101,6 +101,7 @@ struct irq_info
101 unsigned short gsi; 101 unsigned short gsi;
102 unsigned char vector; 102 unsigned char vector;
103 unsigned char flags; 103 unsigned char flags;
104 uint16_t domid;
104 } pirq; 105 } pirq;
105 } u; 106 } u;
106}; 107};
@@ -186,6 +187,7 @@ static void xen_irq_info_pirq_init(unsigned irq,
186 unsigned short pirq, 187 unsigned short pirq,
187 unsigned short gsi, 188 unsigned short gsi,
188 unsigned short vector, 189 unsigned short vector,
190 uint16_t domid,
189 unsigned char flags) 191 unsigned char flags)
190{ 192{
191 struct irq_info *info = info_for_irq(irq); 193 struct irq_info *info = info_for_irq(irq);
@@ -195,6 +197,7 @@ static void xen_irq_info_pirq_init(unsigned irq,
195 info->u.pirq.pirq = pirq; 197 info->u.pirq.pirq = pirq;
196 info->u.pirq.gsi = gsi; 198 info->u.pirq.gsi = gsi;
197 info->u.pirq.vector = vector; 199 info->u.pirq.vector = vector;
200 info->u.pirq.domid = domid;
198 info->u.pirq.flags = flags; 201 info->u.pirq.flags = flags;
199} 202}
200 203
@@ -656,7 +659,7 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi,
656 goto out; 659 goto out;
657 } 660 }
658 661
659 xen_irq_info_pirq_init(irq, 0, pirq, gsi, irq_op.vector, 662 xen_irq_info_pirq_init(irq, 0, pirq, gsi, irq_op.vector, DOMID_SELF,
660 shareable ? PIRQ_SHAREABLE : 0); 663 shareable ? PIRQ_SHAREABLE : 0);
661 664
662 pirq_query_unmask(irq); 665 pirq_query_unmask(irq);
@@ -707,7 +710,8 @@ int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc)
707} 710}
708 711
709int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, 712int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
710 int pirq, int vector, const char *name) 713 int pirq, int vector, const char *name,
714 domid_t domid)
711{ 715{
712 int irq, ret; 716 int irq, ret;
713 717
@@ -720,7 +724,7 @@ int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
720 irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_edge_irq, 724 irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_edge_irq,
721 name); 725 name);
722 726
723 xen_irq_info_pirq_init(irq, 0, pirq, 0, vector, 0); 727 xen_irq_info_pirq_init(irq, 0, pirq, 0, vector, domid, 0);
724 ret = irq_set_msi_desc(irq, msidesc); 728 ret = irq_set_msi_desc(irq, msidesc);
725 if (ret < 0) 729 if (ret < 0)
726 goto error_irq; 730 goto error_irq;
@@ -749,9 +753,16 @@ int xen_destroy_irq(int irq)
749 753
750 if (xen_initial_domain()) { 754 if (xen_initial_domain()) {
751 unmap_irq.pirq = info->u.pirq.pirq; 755 unmap_irq.pirq = info->u.pirq.pirq;
752 unmap_irq.domid = DOMID_SELF; 756 unmap_irq.domid = info->u.pirq.domid;
753 rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq); 757 rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq);
754 if (rc) { 758 /* If another domain quits without making the pci_disable_msix
759 * call, the Xen hypervisor takes care of freeing the PIRQs
760 * (free_domain_pirqs).
761 */
762 if ((rc == -ESRCH && info->u.pirq.domid != DOMID_SELF))
763 printk(KERN_INFO "domain %d does not have %d anymore\n",
764 info->u.pirq.domid, info->u.pirq.pirq);
765 else if (rc) {
755 printk(KERN_WARNING "unmap irq failed %d\n", rc); 766 printk(KERN_WARNING "unmap irq failed %d\n", rc);
756 goto out; 767 goto out;
757 } 768 }
@@ -786,6 +797,12 @@ out:
786 return irq; 797 return irq;
787} 798}
788 799
800
801int xen_pirq_from_irq(unsigned irq)
802{
803 return pirq_from_irq(irq);
804}
805EXPORT_SYMBOL_GPL(xen_pirq_from_irq);
789int bind_evtchn_to_irq(unsigned int evtchn) 806int bind_evtchn_to_irq(unsigned int evtchn)
790{ 807{
791 int irq; 808 int irq;
@@ -1532,6 +1549,18 @@ void xen_poll_irq(int irq)
1532 xen_poll_irq_timeout(irq, 0 /* no timeout */); 1549 xen_poll_irq_timeout(irq, 0 /* no timeout */);
1533} 1550}
1534 1551
1552/* Check whether the IRQ line is shared with other guests. */
1553int xen_test_irq_shared(int irq)
1554{
1555 struct irq_info *info = info_for_irq(irq);
1556 struct physdev_irq_status_query irq_status = { .irq = info->u.pirq.pirq };
1557
1558 if (HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status))
1559 return 0;
1560 return !(irq_status.flags & XENIRQSTAT_shared);
1561}
1562EXPORT_SYMBOL_GPL(xen_test_irq_shared);
1563
1535void xen_irq_resume(void) 1564void xen_irq_resume(void)
1536{ 1565{
1537 unsigned int cpu, evtchn; 1566 unsigned int cpu, evtchn;