]> xenbits.xensource.com Git - libvirt.git/commitdiff
pciResetDevice: use inactive devices to determine safe reset
authorChris Wright <chrisw@redhat.com>
Mon, 26 Jul 2010 16:43:04 +0000 (18:43 +0200)
committerDaniel Veillard <veillard@redhat.com>
Mon, 26 Jul 2010 16:43:04 +0000 (18:43 +0200)
When doing a PCI secondary bus reset, we must be sure that there are no
active devices on the same bus segment.  The active device tracking is
designed to only track host devices that are active in use by guests.
This ignores host devices that are actively in use by the host.  So the
current logic will reset host devices.

Switch this logic around and allow sbus reset when we are assigning all
devices behind a bridge to the same guest at guest startup or as a result
of a single attach-device command.

* src/util/pci.h: change signature of pciResetDevice to add an
  inactive devices list
* src/qemu/qemu_driver.c src/xen/xen_driver.c: use (or not) the new
  functionality of pciResetDevice() depending on the place of use
* src/util/pci.c: implement the interface and logic changes

src/qemu/qemu_driver.c
src/util/pci.c
src/util/pci.h
src/xen/xen_driver.c

index 63ddd35fb5d8649df8c364b959aaaf607382ec43..45a2cfcaaec74d0292a12826ae2976b802850d1a 100644 (file)
@@ -3107,7 +3107,7 @@ qemuPrepareHostdevPCIDevices(struct qemud_driver *driver,
      * reset them */
     for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
         pciDevice *dev = pciDeviceListGet(pcidevs, i);
-        if (pciResetDevice(dev, driver->activePciHostdevs) < 0)
+        if (pciResetDevice(dev, driver->activePciHostdevs, pcidevs) < 0)
             goto cleanup;
     }
 
@@ -3253,7 +3253,7 @@ qemuDomainReAttachHostdevDevices(struct qemud_driver *driver,
 
     for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
         pciDevice *dev = pciDeviceListGet(pcidevs, i);
-        if (pciResetDevice(dev, driver->activePciHostdevs) < 0) {
+        if (pciResetDevice(dev, driver->activePciHostdevs, pcidevs) < 0) {
             virErrorPtr err = virGetLastError();
             VIR_ERROR(_("Failed to reset PCI device: %s"),
                       err ? err->message : _("unknown error"));
@@ -8995,7 +8995,7 @@ static int qemudDomainDetachHostPciDevice(struct qemud_driver *driver,
     else {
         pciDeviceSetManaged(pci, detach->managed);
         pciDeviceListDel(driver->activePciHostdevs, pci);
-        if (pciResetDevice(pci, driver->activePciHostdevs) < 0)
+        if (pciResetDevice(pci, driver->activePciHostdevs, NULL) < 0)
             ret = -1;
         qemudReattachManagedDevice(pci, driver);
         pciFreeDevice(pci);
@@ -11620,7 +11620,7 @@ qemudNodeDeviceReset (virNodeDevicePtr dev)
 
     qemuDriverLock(driver);
 
-    if (pciResetDevice(pci, driver->activePciHostdevs) < 0)
+    if (pciResetDevice(pci, driver->activePciHostdevs, NULL) < 0)
         goto out;
 
     ret = 0;
index 6d0ca24f6c19672c4a2c21900290ec467e286f5e..1c10067d972a71bdff22993a8112fc3419fc3053 100644 (file)
@@ -440,11 +440,11 @@ pciDetectPowerManagementReset(pciDevice *dev)
     return 0;
 }
 
-/* Any active devices other than the one supplied on the same domain/bus ? */
+/* Any active devices on the same domain/bus ? */
 static int
 pciSharesBusWithActive(pciDevice *dev, pciDevice *check, void *data)
 {
-    pciDeviceList *activeDevs = data;
+    pciDeviceList *inactiveDevs = data;
 
     /* Different domain, different bus, or simply identical device */
     if (dev->domain != check->domain ||
@@ -453,7 +453,8 @@ pciSharesBusWithActive(pciDevice *dev, pciDevice *check, void *data)
          dev->function == check->function))
         return 0;
 
-    if (activeDevs && !pciDeviceListFind(activeDevs, check))
+    /* same bus, but inactive, i.e. about to be assigned to guest */
+    if (inactiveDevs && pciDeviceListFind(inactiveDevs, check))
         return 0;
 
     return 1;
@@ -461,11 +462,11 @@ pciSharesBusWithActive(pciDevice *dev, pciDevice *check, void *data)
 
 static pciDevice *
 pciBusContainsActiveDevices(pciDevice *dev,
-                            pciDeviceList *activeDevs)
+                            pciDeviceList *inactiveDevs)
 {
     pciDevice *active = NULL;
     if (pciIterDevices(pciSharesBusWithActive,
-                       dev, &active, activeDevs) < 0)
+                       dev, &active, inactiveDevs) < 0)
         return NULL;
     return active;
 }
@@ -512,7 +513,7 @@ pciGetParentDevice(pciDevice *dev)
  */
 static int
 pciTrySecondaryBusReset(pciDevice *dev,
-                        pciDeviceList *activeDevs)
+                        pciDeviceList *inactiveDevs)
 {
     pciDevice *parent, *conflict;
     uint8_t config_space[PCI_CONF_LEN];
@@ -524,7 +525,7 @@ pciTrySecondaryBusReset(pciDevice *dev,
      * In future, we could allow it so long as those devices
      * are not in use by the host or other guests.
      */
-    if ((conflict = pciBusContainsActiveDevices(dev, activeDevs))) {
+    if ((conflict = pciBusContainsActiveDevices(dev, inactiveDevs))) {
         pciReportError(VIR_ERR_NO_SUPPORT,
                        _("Active %s devices on bus with %s, not doing bus reset"),
                        conflict->name, dev->name);
@@ -642,7 +643,8 @@ pciInitDevice(pciDevice *dev)
 
 int
 pciResetDevice(pciDevice *dev,
-               pciDeviceList *activeDevs)
+               pciDeviceList *activeDevs,
+               pciDeviceList *inactiveDevs)
 {
     int ret = -1;
 
@@ -670,7 +672,7 @@ pciResetDevice(pciDevice *dev,
 
     /* Bus reset is not an option with the root bus */
     if (ret < 0 && dev->bus != 0)
-        ret = pciTrySecondaryBusReset(dev, activeDevs);
+        ret = pciTrySecondaryBusReset(dev, inactiveDevs);
 
     if (ret < 0) {
         virErrorPtr err = virGetLastError();
index 9aef81f9e29031f7fa537c06bd30486ea9298674..b767930bbccecd7bde26248f33e74cc65369c7ac 100644 (file)
@@ -35,7 +35,8 @@ void       pciFreeDevice     (pciDevice     *dev);
 int        pciDettachDevice  (pciDevice     *dev, pciDeviceList *activeDevs);
 int        pciReAttachDevice (pciDevice     *dev, pciDeviceList *activeDevs);
 int        pciResetDevice    (pciDevice     *dev,
-                              pciDeviceList *activeDevs);
+                              pciDeviceList *activeDevs,
+                              pciDeviceList *inactiveDevs);
 void      pciDeviceSetManaged(pciDevice     *dev,
                               unsigned       managed);
 unsigned  pciDeviceGetManaged(pciDevice     *dev);
index b55e4945308d01e13025c316ed6b52b9c444404b..d121ea4c3f048dc36df9f3f9ffb0379d24e3192e 100644 (file)
@@ -1892,7 +1892,7 @@ xenUnifiedNodeDeviceReset (virNodeDevicePtr dev)
     if (!pci)
         return -1;
 
-    if (pciResetDevice(pci, NULL) < 0)
+    if (pciResetDevice(pci, NULL, NULL) < 0)
         goto out;
 
     ret = 0;