aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/pci
diff options
context:
space:
mode:
authorJan Beulich <JBeulich@suse.com>2011-09-22 04:17:57 -0400
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2011-09-22 16:23:46 -0400
commit55e901fc1f03dd8437f877813c68b6014cdbeefd (patch)
tree0f3d81f7bb534a89fcc59e3109246ca5cd75935b /arch/x86/pci
parent6810df88dcfc22de267caf23eb072ffb97b3c411 (diff)
xen/pci: support multi-segment systems
Now that the hypercall interface changes are in -unstable, make the kernel side code not ignore the segment (aka domain) number anymore (which results in pretty odd behavior on such systems). Rather, if only the old interfaces are available, don't call them for devices on non-zero segments at all. Signed-off-by: Jan Beulich <jbeulich@suse.com> [v1: Edited git description] Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'arch/x86/pci')
-rw-r--r--arch/x86/pci/xen.c22
1 files changed, 19 insertions, 3 deletions
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index f567965c0620..265fa8814ccd 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -185,6 +185,8 @@ static void xen_teardown_msi_irq(unsigned int irq)
185} 185}
186 186
187#ifdef CONFIG_XEN_DOM0 187#ifdef CONFIG_XEN_DOM0
188static bool __read_mostly pci_seg_supported = true;
189
188static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) 190static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
189{ 191{
190 int ret = 0; 192 int ret = 0;
@@ -202,10 +204,11 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
202 204
203 memset(&map_irq, 0, sizeof(map_irq)); 205 memset(&map_irq, 0, sizeof(map_irq));
204 map_irq.domid = domid; 206 map_irq.domid = domid;
205 map_irq.type = MAP_PIRQ_TYPE_MSI; 207 map_irq.type = MAP_PIRQ_TYPE_MSI_SEG;
206 map_irq.index = -1; 208 map_irq.index = -1;
207 map_irq.pirq = -1; 209 map_irq.pirq = -1;
208 map_irq.bus = dev->bus->number; 210 map_irq.bus = dev->bus->number |
211 (pci_domain_nr(dev->bus) << 16);
209 map_irq.devfn = dev->devfn; 212 map_irq.devfn = dev->devfn;
210 213
211 if (type == PCI_CAP_ID_MSIX) { 214 if (type == PCI_CAP_ID_MSIX) {
@@ -222,7 +225,20 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
222 map_irq.entry_nr = msidesc->msi_attrib.entry_nr; 225 map_irq.entry_nr = msidesc->msi_attrib.entry_nr;
223 } 226 }
224 227
225 ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq); 228 ret = -EINVAL;
229 if (pci_seg_supported)
230 ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq,
231 &map_irq);
232 if (ret == -EINVAL && !pci_domain_nr(dev->bus)) {
233 map_irq.type = MAP_PIRQ_TYPE_MSI;
234 map_irq.index = -1;
235 map_irq.pirq = -1;
236 map_irq.bus = dev->bus->number;
237 ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq,
238 &map_irq);
239 if (ret != -EINVAL)
240 pci_seg_supported = false;
241 }
226 if (ret) { 242 if (ret) {
227 dev_warn(&dev->dev, "xen map irq failed %d for %d domain\n", 243 dev_warn(&dev->dev, "xen map irq failed %d for %d domain\n",
228 ret, domid); 244 ret, domid);