diff options
author | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2011-04-14 11:17:36 -0400 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2011-04-14 11:17:36 -0400 |
commit | beafbdc1df02877612dc9039c1de0639921fddec (patch) | |
tree | 6103bd53db2858462c38bcf03b36eb7aad701576 | |
parent | c55fa78b13b32d3f19e19cd0c8b9378fdc09e521 (diff) |
xen/irq: Check if the PCI device is owned by a domain different than DOMID_SELF.
We check if there is a domain owner for the PCI device. In case of failure
(meaning no domain has registered for this device) we make DOMID_SELF the owner.
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
[v2: deal with rebasing on v2.6.37-1]
[v3: deal with rebasing on stable/irq.cleanup]
[v4: deal with rebasing on stable/irq.ween_of_nr_irqs]
[v5: deal with rebasing on v2.6.39-rc3]
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Acked-by: Xiantao Zhang <xiantao.zhang@intel.com>
-rw-r--r-- | arch/x86/pci/xen.c | 21 | ||||
-rw-r--r-- | drivers/xen/events.c | 12 | ||||
-rw-r--r-- | include/xen/events.h | 3 |
3 files changed, 26 insertions, 10 deletions
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 6075f2d65335..393981feb12f 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c | |||
@@ -108,7 +108,8 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
108 | } | 108 | } |
109 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, 0, | 109 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, 0, |
110 | (type == PCI_CAP_ID_MSIX) ? | 110 | (type == PCI_CAP_ID_MSIX) ? |
111 | "msi-x" : "msi"); | 111 | "msi-x" : "msi", |
112 | DOMID_SELF); | ||
112 | if (irq < 0) | 113 | if (irq < 0) |
113 | goto error; | 114 | goto error; |
114 | dev_dbg(&dev->dev, | 115 | dev_dbg(&dev->dev, |
@@ -148,7 +149,8 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
148 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0, | 149 | irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0, |
149 | (type == PCI_CAP_ID_MSIX) ? | 150 | (type == PCI_CAP_ID_MSIX) ? |
150 | "pcifront-msi-x" : | 151 | "pcifront-msi-x" : |
151 | "pcifront-msi"); | 152 | "pcifront-msi", |
153 | DOMID_SELF); | ||
152 | if (irq < 0) | 154 | if (irq < 0) |
153 | goto free; | 155 | goto free; |
154 | i++; | 156 | i++; |
@@ -190,9 +192,16 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
190 | 192 | ||
191 | list_for_each_entry(msidesc, &dev->msi_list, list) { | 193 | list_for_each_entry(msidesc, &dev->msi_list, list) { |
192 | struct physdev_map_pirq map_irq; | 194 | struct physdev_map_pirq map_irq; |
195 | domid_t domid; | ||
196 | |||
197 | domid = ret = xen_find_device_domain_owner(dev); | ||
198 | /* N.B. Casting int's -ENODEV to uint16_t results in 0xFFED, | ||
199 | * hence check ret value for < 0. */ | ||
200 | if (ret < 0) | ||
201 | domid = DOMID_SELF; | ||
193 | 202 | ||
194 | memset(&map_irq, 0, sizeof(map_irq)); | 203 | memset(&map_irq, 0, sizeof(map_irq)); |
195 | map_irq.domid = DOMID_SELF; | 204 | map_irq.domid = domid; |
196 | map_irq.type = MAP_PIRQ_TYPE_MSI; | 205 | map_irq.type = MAP_PIRQ_TYPE_MSI; |
197 | map_irq.index = -1; | 206 | map_irq.index = -1; |
198 | map_irq.pirq = -1; | 207 | map_irq.pirq = -1; |
@@ -215,14 +224,16 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
215 | 224 | ||
216 | ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); | 225 | ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); |
217 | if (ret) { | 226 | if (ret) { |
218 | dev_warn(&dev->dev, "xen map irq failed %d\n", ret); | 227 | dev_warn(&dev->dev, "xen map irq failed %d for %d domain\n", |
228 | ret, domid); | ||
219 | goto out; | 229 | goto out; |
220 | } | 230 | } |
221 | 231 | ||
222 | ret = xen_bind_pirq_msi_to_irq(dev, msidesc, | 232 | ret = xen_bind_pirq_msi_to_irq(dev, msidesc, |
223 | map_irq.pirq, map_irq.index, | 233 | map_irq.pirq, map_irq.index, |
224 | (type == PCI_CAP_ID_MSIX) ? | 234 | (type == PCI_CAP_ID_MSIX) ? |
225 | "msi-x" : "msi"); | 235 | "msi-x" : "msi", |
236 | domid); | ||
226 | if (ret < 0) | 237 | if (ret < 0) |
227 | goto out; | 238 | goto out; |
228 | } | 239 | } |
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 42d6c930cc87..ac0e22826357 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 | }; |
@@ -184,6 +185,7 @@ static void xen_irq_info_pirq_init(unsigned irq, | |||
184 | unsigned short pirq, | 185 | unsigned short pirq, |
185 | unsigned short gsi, | 186 | unsigned short gsi, |
186 | unsigned short vector, | 187 | unsigned short vector, |
188 | uint16_t domid, | ||
187 | unsigned char flags) | 189 | unsigned char flags) |
188 | { | 190 | { |
189 | struct irq_info *info = info_for_irq(irq); | 191 | struct irq_info *info = info_for_irq(irq); |
@@ -193,6 +195,7 @@ static void xen_irq_info_pirq_init(unsigned irq, | |||
193 | info->u.pirq.pirq = pirq; | 195 | info->u.pirq.pirq = pirq; |
194 | info->u.pirq.gsi = gsi; | 196 | info->u.pirq.gsi = gsi; |
195 | info->u.pirq.vector = vector; | 197 | info->u.pirq.vector = vector; |
198 | info->u.pirq.domid = domid; | ||
196 | info->u.pirq.flags = flags; | 199 | info->u.pirq.flags = flags; |
197 | } | 200 | } |
198 | 201 | ||
@@ -655,7 +658,7 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi, | |||
655 | goto out; | 658 | goto out; |
656 | } | 659 | } |
657 | 660 | ||
658 | xen_irq_info_pirq_init(irq, 0, pirq, gsi, irq_op.vector, | 661 | xen_irq_info_pirq_init(irq, 0, pirq, gsi, irq_op.vector, DOMID_SELF, |
659 | shareable ? PIRQ_SHAREABLE : 0); | 662 | shareable ? PIRQ_SHAREABLE : 0); |
660 | 663 | ||
661 | out: | 664 | out: |
@@ -680,7 +683,8 @@ int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc) | |||
680 | } | 683 | } |
681 | 684 | ||
682 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, | 685 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, |
683 | int pirq, int vector, const char *name) | 686 | int pirq, int vector, const char *name, |
687 | domid_t domid) | ||
684 | { | 688 | { |
685 | int irq, ret; | 689 | int irq, ret; |
686 | 690 | ||
@@ -693,7 +697,7 @@ int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, | |||
693 | irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_level_irq, | 697 | irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_level_irq, |
694 | name); | 698 | name); |
695 | 699 | ||
696 | xen_irq_info_pirq_init(irq, 0, pirq, 0, vector, 0); | 700 | xen_irq_info_pirq_init(irq, 0, pirq, 0, vector, domid, 0); |
697 | ret = irq_set_msi_desc(irq, msidesc); | 701 | ret = irq_set_msi_desc(irq, msidesc); |
698 | if (ret < 0) | 702 | if (ret < 0) |
699 | goto error_irq; | 703 | goto error_irq; |
@@ -722,7 +726,7 @@ int xen_destroy_irq(int irq) | |||
722 | 726 | ||
723 | if (xen_initial_domain()) { | 727 | if (xen_initial_domain()) { |
724 | unmap_irq.pirq = info->u.pirq.pirq; | 728 | unmap_irq.pirq = info->u.pirq.pirq; |
725 | unmap_irq.domid = DOMID_SELF; | 729 | unmap_irq.domid = info->u.pirq.domid; |
726 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq); | 730 | rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq); |
727 | if (rc) { | 731 | if (rc) { |
728 | printk(KERN_WARNING "unmap irq failed %d\n", rc); | 732 | printk(KERN_WARNING "unmap irq failed %d\n", rc); |
diff --git a/include/xen/events.h b/include/xen/events.h index f1b87ad48ac7..9aecc0b5a0e6 100644 --- a/include/xen/events.h +++ b/include/xen/events.h | |||
@@ -85,7 +85,8 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi, | |||
85 | int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc); | 85 | int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc); |
86 | /* Bind an PSI pirq to an irq. */ | 86 | /* Bind an PSI pirq to an irq. */ |
87 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, | 87 | int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, |
88 | int pirq, int vector, const char *name); | 88 | int pirq, int vector, const char *name, |
89 | domid_t domid); | ||
89 | #endif | 90 | #endif |
90 | 91 | ||
91 | /* De-allocates the above mentioned physical interrupt. */ | 92 | /* De-allocates the above mentioned physical interrupt. */ |