commit 7551a514dd944a5155747071135bac11deb61c43
Author: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Date: Thu Jun 25 18:30:25 2009 +0100
passthrough: use devfn instead of slots as the unit for pass-through
This is part of support for multi-function PCI devices in guests
Instead of reading a slot number from xend, read a devfn.
This and subsequent other changes will allow xend to ask
for more than one function to be inserted into a single slot -
by specifying which function of the slot should be used.
This is a minimal patch for this change. A subsequent
patch that has a lot of noise to rename slot to devfn follows.
This patch breaks compatibility with xend and corresponding
patches to xend are required.
Cc: Dexuan Cui <dexuan.cui@xxxxxxxxx>
Cc: Masaki Kanno <kanno.masaki@xxxxxxxxxxxxxx>
Signed-off-by: Simon Horman <horms@xxxxxxxxxxxx>
[3/8; cross-compatibility issues with xen-unstable.hg]
---
hw/pass-through.c | 40 ++++++++++++++--------------
hw/pci.h | 7 +++-
hw/piix4acpi.c | 75 ++++++++++++++++++++++++++++++++++++++---------------
3 files changed, 79 insertions(+), 43 deletions(-)
diff --git a/hw/pass-through.c b/hw/pass-through.c
index 07ca751..d19fb82 100644
--- a/hw/pass-through.c
+++ b/hw/pass-through.c
@@ -103,7 +103,7 @@ struct php_dev {
};
struct dpci_infos {
- struct php_dev php_devs[NR_PCI_DEV];
+ struct php_dev php_devs[NR_PCI_DEVFN];
PCIBus *e_bus;
struct pci_access *pci_access;
@@ -859,7 +859,7 @@ static int parse_bdf(char **str, int *seg, int *bus, int
*dev, int *func,
}
else
{
- *vslot = AUTO_PHP_SLOT;
+ *vslot = AUTO_PHP_DEVFN;
*opt = token;
}
@@ -903,30 +903,30 @@ static int pci_slot_match(int bus, int dev, int func, int
slot)
}
/* Insert a new pass-through device into a specific pci slot.
- * input dom:bus:dev.func@slot, chose free one if slot == AUTO_PHP_SLOT
+ * input dom:bus:dev.func@slot, chose free one if slot == AUTO_PHP_DEVFN
* return -2: requested slot not available
* -1: no free slots
* >=0: the new hotplug slot
*/
-static int __insert_to_pci_slot(int bus, int dev, int func, int slot,
+static int __insert_to_pci_slot(int bus, int dev, int func, int devfn,
char *opt)
{
PCIBus *e_bus = dpci_infos.e_bus;
+ int slot;
- /* preferred virt pci slot */
- if ( slot != AUTO_PHP_SLOT)
+ /* preferred virt pci devfn */
+ if ( devfn != AUTO_PHP_DEVFN )
{
- if ( !test_pci_slot(slot) &&
- !pci_devfn_in_use(e_bus, PCI_DEVFN(slot, 0)) )
+ if ( !test_pci_slot(devfn) && !pci_devfn_in_use(e_bus, devfn) )
goto found;
return -2;
}
- /* slot == 0, pick up a free one */
+ /* pick a free slot */
for ( slot = 0; slot < NR_PCI_DEV; slot++ )
{
- if ( !test_pci_slot(slot) &&
- !pci_devfn_in_use(e_bus, PCI_DEVFN(slot, 0)) )
+ devfn = PCI_DEVFN(slot, 0);
+ if ( !test_pci_slot(devfn) && !pci_devfn_in_use(e_bus, devfn) )
goto found;
}
@@ -934,12 +934,12 @@ static int __insert_to_pci_slot(int bus, int dev, int
func, int slot,
return -1;
found:
- dpci_infos.php_devs[slot].valid = 1;
- dpci_infos.php_devs[slot].r_bus = bus;
- dpci_infos.php_devs[slot].r_dev = dev;
- dpci_infos.php_devs[slot].r_func = func;
- dpci_infos.php_devs[slot].opt = opt;
- return slot;
+ dpci_infos.php_devs[devfn].valid = 1;
+ dpci_infos.php_devs[devfn].r_bus = bus;
+ dpci_infos.php_devs[devfn].r_dev = dev;
+ dpci_infos.php_devs[devfn].r_func = func;
+ dpci_infos.php_devs[devfn].opt = opt;
+ return devfn;
}
/* Insert a new pass-through device into a specific pci slot.
@@ -966,7 +966,7 @@ int insert_to_pci_slot(char *bdf_slt)
*/
int test_pci_slot(int slot)
{
- if ( slot < 0 || slot >= NR_PCI_DEV )
+ if ( slot < 0 || slot >= NR_PCI_DEVFN )
return -1;
if ( dpci_infos.php_devs[slot].valid )
@@ -987,7 +987,7 @@ int bdf_to_slot(char *bdf_str)
}
/* locate the virtual pci slot for this VTd device */
- for ( i = 0; i < NR_PCI_DEV; i++ )
+ for ( i = 0; i < NR_PCI_DEVFN; i++ )
{
if ( pci_slot_match(bus, dev, func, i) )
return i;
@@ -4037,7 +4037,7 @@ static struct pt_dev * register_real_device(PCIBus *e_bus,
/* Register device */
assigned_device = (struct pt_dev *) pci_register_device(e_bus, e_dev_name,
- sizeof(struct pt_dev), PCI_DEVFN(e_slot, 0),
+ sizeof(struct pt_dev), e_slot,
pt_pci_read_config, pt_pci_write_config);
if ( assigned_device == NULL )
{
diff --git a/hw/pci.h b/hw/pci.h
index d45b80c..b5947f3 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -255,8 +255,11 @@ void pci_info(void);
PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
pci_map_irq_fn map_irq, const char *name);
-#define NR_PCI_DEV 32
-#define AUTO_PHP_SLOT NR_PCI_DEV
+#define NR_PCI_FUNC 8
+#define NR_PCI_DEV 32
+#define NR_PCI_DEVFN (NR_PCI_FUNC * NR_PCI_DEV)
+#define AUTO_PHP_SLOT NR_PCI_DEV
+#define AUTO_PHP_DEVFN NR_PCI_DEVFN
int insert_to_pci_slot(char*);
int test_pci_slot(int);
diff --git a/hw/piix4acpi.c b/hw/piix4acpi.c
index d5c5c35..836abd5 100644
--- a/hw/piix4acpi.c
+++ b/hw/piix4acpi.c
@@ -33,6 +33,8 @@
#include <xen/hvm/ioreq.h>
#include <xen/hvm/params.h>
+#include <pci/header.h>
+
/* PM1a_CNT bits, as defined in the ACPI specification. */
#define SCI_EN (1 << 0)
#define GBL_RLS (1 << 2)
@@ -276,7 +278,7 @@ static void acpi_php_writeb(void *opaque, uint32_t addr,
uint32_t val)
hotplug_slots->plug_slot = 0;
/* power off the slot */
- power_off_php_slot(slot);
+ power_off_php_slot(PCI_DEVFN(slot, 0));
/* signal the CP ACPI hot remove done. */
xenstore_record_dm_state("pci-removed");
@@ -459,17 +461,32 @@ static void acpi_sci_intr(GPEState *s)
}
}
-void acpi_php_del(int slot)
+void acpi_php_del(int devfn)
{
GPEState *s = &gpe_state;
+ int slot, func;
+
+ slot = PCI_SLOT(devfn);
+ func = PCI_FUNC(devfn);
- if ( test_pci_slot(slot) < 0 ) {
- fprintf(logfile, "hot remove: pci slot %d "
- "is not used by a hotplug device.\n", slot);
+ if ( test_pci_slot(devfn) < 0 ) {
+ fprintf(logfile, "hot remove: pci slot 0x%02x, function 0x%x "
+ "is not used by a hotplug device.\n", slot, func);
return;
}
+ /* ACPI PHP can only work on slots
+ * So only remove zero-functions -
+ * which will remove all other fucntions of the same device in the
+ * guest.
+ */
+ if ( func ) {
+ fprintf(logfile, "hot remove: Attempt to remove non-zero function "
+ "slot=0x%02x func=0x%0x.\n", slot, func);
+ return;
+ }
+
/* update the php controller status */
php_slots.plug_evt = PHP_EVT_REMOVE;
php_slots.plug_slot = slot;
@@ -478,18 +495,19 @@ void acpi_php_del(int slot)
acpi_sci_intr(s);
}
-void acpi_php_add(int slot)
+void acpi_php_add(int devfn)
{
GPEState *s = &gpe_state;
char ret_str[30];
+ int slot, func;
- if ( slot < 0 ) {
- fprintf(logfile, "hot add pci slot %d exceed.\n", slot);
+ if ( devfn < 0 ) {
+ fprintf(logfile, "hot add pci devfn %d exceed.\n", devfn);
- if ( slot == -1 )
- sprintf(ret_str, "no free hotplug slots");
- else if ( slot == -2 )
- sprintf(ret_str, "wrong bdf or vslot");
+ if ( devfn == -1 )
+ sprintf(ret_str, "no free hotplug devfn");
+ else if ( devfn == -2 )
+ sprintf(ret_str, "wrong bdf or vdevfn");
if ( strlen(ret_str) > 0 )
xenstore_record_dm("parameter", ret_str);
@@ -497,25 +515,40 @@ void acpi_php_add(int slot)
return;
}
- /* update the php controller status */
- php_slots.plug_evt = PHP_EVT_ADD;
- php_slots.plug_slot = slot;
+ /* ACPI PHP can only work on slots
+ * For function 0 we do a full hot-add.
+ * For other functions we just register the device with the hypervisor.
+ * Assuming that function 0 is added after non-zero functions,
+ * its ACPI PHP event will cause all previously registered functions
+ * to be added to the guest.
+ */
- /* update the slot status as present */
- php_slots.status[slot] = 0xf;
+ slot = PCI_SLOT(devfn);
+ func = PCI_FUNC(devfn);
- /* power on the slot */
- power_on_php_slot(slot);
+ if ( !func )
+ {
+ /* update the php controller status */
+ php_slots.plug_evt = PHP_EVT_ADD;
+ php_slots.plug_slot = slot;
+
+ /* update the slot status as present */
+ php_slots.status[slot] = 0xf;
+ }
+
+ /* power on the function */
+ power_on_php_slot(devfn);
/* tell Control panel which slot for the new pass-throgh dev */
- sprintf(ret_str, "0x%02x", slot);
+ sprintf(ret_str, "0x%02x", devfn);
xenstore_record_dm("parameter", ret_str);
/* signal the CP ACPI hot insert done */
xenstore_record_dm_state("pci-inserted");
/* generate a SCI interrupt */
- acpi_sci_intr(s);
+ if ( !func )
+ acpi_sci_intr(s);
}
#endif /* CONFIG_PASSTHROUGH */
--
generated by git-patchbot for /home/xen/git/qemu-xen-unstable.git
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|