Implement the new methods in the QEMU driver by parsing
the node device XML to obtain the PCI device details
and then calling the appropriate PCI utility function.
Signed-off-by: Mark McLoughlin <markmc(a)redhat.com>
---
ChangeLog | 5 ++
src/qemu_driver.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 132 insertions(+), 3 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index dd8241d..62a286f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Tue Feb 24 22:08:15 GMT 2009 Mark McLoughlin <markmc(a)redhat.com>
+
+ * src/qemu_driver.c: implement the new methods in the
+ QEMU driver.
+
Tue Feb 24 22:02:32 GMT 2009 Mark McLoughlin <markmc(a)redhat.com>
* qemud/remote*, src/remote_internal.c: plumb the new
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index c2dfc71..7b13c5e 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -68,6 +68,8 @@
#include "memory.h"
#include "uuid.h"
#include "domain_conf.h"
+#include "node_device_conf.h"
+#include "pci.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -4470,6 +4472,128 @@ cleanup:
return dom;
}
+static int
+qemudNodeDeviceGetPciInfo (virNodeDevicePtr dev,
+ unsigned *vendor,
+ unsigned *product,
+ unsigned *domain,
+ unsigned *bus,
+ unsigned *slot,
+ unsigned *function)
+{
+ virNodeDeviceDefPtr def = NULL;
+ virNodeDevCapsDefPtr cap;
+ char *xml = NULL;
+ int ret = -1;
+
+ xml = virNodeDeviceGetXMLDesc(dev, 0);
+ if (!xml)
+ goto out;
+
+ def = virNodeDeviceDefParseString(dev->conn, xml);
+ if (!def)
+ goto out;
+
+ cap = def->caps;
+ while (cap) {
+ if (cap->type == VIR_NODE_DEV_CAP_PCI_DEV) {
+ *vendor = cap->data.pci_dev.vendor;
+ *product = cap->data.pci_dev.product;
+ *domain = cap->data.pci_dev.domain;
+ *bus = cap->data.pci_dev.bus;
+ *slot = cap->data.pci_dev.slot;
+ *function = cap->data.pci_dev.function;
+ break;
+ }
+
+ cap = cap->next;
+ }
+
+ if (!cap) {
+ qemudReportError(dev->conn, NULL, NULL, VIR_ERR_INVALID_ARG,
+ _("device %s is not a PCI device"), dev->name);
+ goto out;
+ }
+
+ ret = 0;
+out:
+ virNodeDeviceDefFree(def);
+ VIR_FREE(xml);
+ return ret;
+}
+
+static int
+qemudNodeDeviceDettach (virNodeDevicePtr dev)
+{
+ pciDevice *pci;
+ unsigned vendor, product, domain, bus, slot, function;
+ int ret = -1;
+
+ if (qemudNodeDeviceGetPciInfo(dev, &vendor, &product,
+ &domain, &bus, &slot, &function) <
0)
+ return -1;
+
+ pci = pciGetDevice(dev->conn, vendor, product, domain, bus, slot, function);
+ if (!pci)
+ return -1;
+
+ if (pciDettachDevice(pci) < 0)
+ goto out;
+
+ ret = 0;
+out:
+ pciFreeDevice(pci);
+ return ret;
+}
+
+static int
+qemudNodeDeviceReAttach (virNodeDevicePtr dev)
+{
+ pciDevice *pci;
+ unsigned vendor, product, domain, bus, slot, function;
+ int ret = -1;
+
+ if (qemudNodeDeviceGetPciInfo(dev, &vendor, &product,
+ &domain, &bus, &slot, &function) <
0)
+ return -1;
+
+ pci = pciGetDevice(dev->conn, vendor, product, domain, bus, slot, function);
+ if (!pci)
+ return -1;
+
+ if (pciReAttachDevice(pci) < 0)
+ goto out;
+
+ ret = 0;
+out:
+ pciFreeDevice(pci);
+ return ret;
+}
+
+static int
+qemudNodeDeviceReset (virNodeDevicePtr dev)
+{
+ pciDevice *pci;
+ unsigned vendor, product, domain, bus, slot, function;
+ int ret = -1;
+
+ if (qemudNodeDeviceGetPciInfo(dev, &vendor, &product,
+ &domain, &bus, &slot, &function) <
0)
+ return -1;
+
+ pci = pciGetDevice(dev->conn, vendor, product, domain, bus, slot, function);
+ if (!pci)
+ return -1;
+
+ if (pciResetDevice(pci) < 0)
+ goto out;
+
+ ret = 0;
+out:
+ pciFreeDevice(pci);
+ return ret;
+}
+
static virDriver qemuDriver = {
VIR_DRV_QEMU,
"QEMU",
@@ -4542,9 +4666,9 @@ static virDriver qemuDriver = {
qemudDomainEventDeregister, /* domainEventDeregister */
qemudDomainMigratePrepare2, /* domainMigratePrepare2 */
qemudDomainMigrateFinish2, /* domainMigrateFinish2 */
- NULL, /* nodeDeviceDettach */
- NULL, /* nodeDeviceReAttach */
- NULL, /* nodeDeviceReset */
+ qemudNodeDeviceDettach, /* nodeDeviceDettach */
+ qemudNodeDeviceReAttach, /* nodeDeviceReAttach */
+ qemudNodeDeviceReset, /* nodeDeviceReset */
};
--
1.6.0.6