ia64/linux-2.6.18-xen.hg

view drivers/pci/setup-irq.c @ 882:8dec4aa9b8b9

PCI pass through: PCIe IO space multiplexing

This is required for more than 16 HVM domain to boot from
PCIe pass through device.

Linux as dom0 exclusively assigns IO space to downstream PCI bridges
and the assignment unit of PCI bridge IO space is 4K. So the only up
to 16 PCIe device can be accessed via IO space within 64K IO ports.
PCI expansion ROM BIOS often uses IO port access to boot from the
device, so on virtualized environment, it means only up to 16 guest
domain can boot from pass-through device.

This patch allows PCIe IO space sharing of pass-through device.
- reassign IO space of PCIe devices specified by
"guestiomuldev=[<segment>:]<bus>:<dev>[,[<segment:><bus>:dev]][,...]"
to be shared.
This is implemented as Linux PCI quirk fixup.

The sharing unit is PCIe switch. Ie IO space of the end point
devices under the same switch will be shared. If there are more than
one switches, two areas of IO space will be used.

- And the driver which arbitrates the accesses to the multiplexed PCIe
IO space. Later qemu-dm will use this.

Limitation:
IO port of IO shared devices can't be accessed from dom0 Linux device
driver. But this wouldn't be a big issue because PCIe specification
discourages the use of IO space and recommends that IO space should be
used only for bootable device with ROM code. OS device driver should
work without IO space access.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Keir Fraser <keir.fraser@citrix.com>
date Thu May 28 09:57:49 2009 +0100 (2009-05-28)
parents 831230e53067
children
line source
1 /*
2 * drivers/pci/setup-irq.c
3 *
4 * Extruded from code written by
5 * Dave Rusling (david.rusling@reo.mts.dec.com)
6 * David Mosberger (davidm@cs.arizona.edu)
7 * David Miller (davem@redhat.com)
8 *
9 * Support routines for initializing a PCI subsystem.
10 */
13 #include <linux/init.h>
14 #include <linux/kernel.h>
15 #include <linux/pci.h>
16 #include <linux/errno.h>
17 #include <linux/ioport.h>
18 #include <linux/cache.h>
21 static void __init
22 pdev_fixup_irq(struct pci_dev *dev,
23 u8 (*swizzle)(struct pci_dev *, u8 *),
24 int (*map_irq)(struct pci_dev *, u8, u8))
25 {
26 u8 pin, slot;
27 int irq;
29 /* If this device is not on the primary bus, we need to figure out
30 which interrupt pin it will come in on. We know which slot it
31 will come in on 'cos that slot is where the bridge is. Each
32 time the interrupt line passes through a PCI-PCI bridge we must
33 apply the swizzle function. */
35 pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
36 /* Cope with 0 and illegal. */
37 if (pin == 0 || pin > 4)
38 pin = 1;
40 /* Follow the chain of bridges, swizzling as we go. */
41 slot = (*swizzle)(dev, &pin);
43 irq = (*map_irq)(dev, slot, pin);
44 if (irq == -1)
45 irq = 0;
46 dev->irq = irq;
48 pr_debug("PCI: fixup irq: (%s) got %d\n",
49 dev->dev.kobj.name, dev->irq);
51 /* Always tell the device, so the driver knows what is
52 the real IRQ to use; the device does not use it. */
53 pcibios_update_irq(dev, irq);
54 }
56 void __init
57 pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *),
58 int (*map_irq)(struct pci_dev *, u8, u8))
59 {
60 struct pci_dev *dev = NULL;
61 while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
62 pdev_fixup_irq(dev, swizzle, map_irq);
63 }
64 }