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>
---
* co-dependent with xend patch
"xend: pass-through: use devfn instead of slots as the unit for pass-through"
Changes
Thu, 21 May 2009 12:09:30 +1000
* __insert_to_pci_slot() should operate on a vdevfn not a vslot when
it automatically allocating a vslot
Thu, 28 May 2009 22:36:54 +1000
* Up-port to 16a3f599db2afcd87137294f8c497597ddcccde1
Index: ioemu-remote/hw/pass-through.c
===================================================================
--- ioemu-remote.orig/hw/pass-through.c 2009-06-15 11:25:44.000000000 +1000
+++ ioemu-remote/hw/pass-through.c 2009-06-15 11:25:45.000000000 +1000
@@ -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 *se
}
else
{
- *vslot = AUTO_PHP_SLOT;
+ *vslot = AUTO_PHP_DEVFN;
*opt = token;
}
@@ -903,30 +903,30 @@ static int pci_slot_match(int bus, int d
}
/* 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,
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_dev
/* 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 )
{
Index: ioemu-remote/hw/pci.h
===================================================================
--- ioemu-remote.orig/hw/pci.h 2009-06-15 11:25:38.000000000 +1000
+++ ioemu-remote/hw/pci.h 2009-06-15 11:25:45.000000000 +1000
@@ -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);
Index: ioemu-remote/hw/piix4acpi.c
===================================================================
--- ioemu-remote.orig/hw/piix4acpi.c 2009-06-15 11:25:38.000000000 +1000
+++ ioemu-remote/hw/piix4acpi.c 2009-06-15 11:25:45.000000000 +1000
@@ -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
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 */
--
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|