Skip to contentSkip to conversation

pcifront/pciback: Fix Handling of Device Disconnect

PATCH New Yosuke Iwamatsu 1 participant 1 message Jul 16, 2008 Xen hypervisor interface

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 pcifront/pciback: Fix Handling of Device Disconnect

When destroying pcifront/pciback, the following message appears in the guest linux kernel log.

WARNING: g.e. still in use!
WARNING: leaking g.e. and page still in use!

This is caused by the wrong disconnect procedure that pcifront terminates the gnttab foreign access before pciback unmaps the ring.

This patch corrects the handling of pcifront/pciback destruction sequence. Firstly pcifront cleans up root buses to ensure no more pci_op is issued, then pciback unmaps the shared ring and finally devices are discarded.

Regards,
-----------------------
Yosuke Iwamatsu
NEC Corporation

pcifront/back: Fix handling of device disconnect.

drivers/xen/pciback/xenbus.c +35 -16
diff -r a682229d0eac drivers/xen/pciback/xenbus.c
@@ -42,22 +42,35 @@ static struct pciback_device *alloc_pdev
 	return pdev;
 }
 
-static void free_pdev(struct pciback_device *pdev)
-{
-	if (pdev->be_watching)
-		unregister_xenbus_watch(&pdev->be_watch);
+static void pciback_disconnect(struct pciback_device *pdev)
+{
+	spin_lock(&pdev->dev_lock);
 
 	/* Ensure the guest can't trigger our handler before removing devices */
-	if (pdev->evtchn_irq != INVALID_EVTCHN_IRQ)
+	if (pdev->evtchn_irq != INVALID_EVTCHN_IRQ) {
 		unbind_from_irqhandler(pdev->evtchn_irq, pdev);
+		pdev->evtchn_irq = INVALID_EVTCHN_IRQ;
+	}
 
 	/* If the driver domain started an op, make sure we complete it or
 	 * delete it before releasing the shared memory */
 	cancel_delayed_work(&pdev->op_work);
 	flush_scheduled_work();
 
-	if (pdev->sh_info)
+	if (pdev->sh_info != NULL) {
 		xenbus_unmap_ring_vfree(pdev->xdev, pdev->sh_area);
+		pdev->sh_info = NULL;
+	}
+
+	spin_unlock(&pdev->dev_lock);
+}
+
+static void free_pdev(struct pciback_device *pdev)
+{
+	if (pdev->be_watching)
+		unregister_xenbus_watch(&pdev->be_watch);
+
+	pciback_disconnect(pdev);
 
 	pciback_release_devices(pdev);
 
@@ -471,16 +484,6 @@ static void pciback_frontend_changed(str
 		pciback_attach(pdev);
 		break;
 
-	case XenbusStateClosing:
-		xenbus_switch_state(xdev, XenbusStateClosed);
-		break;
-
-	case XenbusStateUnknown:
-	case XenbusStateClosed:
-		dev_dbg(&xdev->dev, "frontend is gone! unregister device\n");
-		device_unregister(&xdev->dev);
-		break;
-
 	case XenbusStateReconfiguring:
 		pciback_reconfigure(pdev);
 		break;
@@ -490,6 +493,22 @@ static void pciback_frontend_changed(str
 		 * Then switch to connected state.
 		 */
 		xenbus_switch_state(xdev, XenbusStateConnected);
+		break;
+
+	case XenbusStateClosing:
+		pciback_disconnect(pdev);
+		xenbus_switch_state(xdev, XenbusStateClosing);
+		break;
+
+	case XenbusStateClosed:
+		pciback_disconnect(pdev);
+		xenbus_switch_state(xdev, XenbusStateClosed);
+		if (xenbus_dev_is_online(xdev))
+			break;
+		/* fall through if not online */
+	case XenbusStateUnknown:
+		dev_dbg(&xdev->dev, "frontend is gone! unregister device\n");
+		device_unregister(&xdev->dev);
 		break;
 
 	default:
drivers/xen/pcifront/xenbus.c +21 -20

65 lines not on this page · raw message

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel