# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1216212696 -3600
# Node ID 5644f68a7912e39585d9cbf3bc0a3800884ae693
# Parent bd4b58143713a9d379570707a755079c7cb4f62d
pcifront/back: Fix handling of device disconnect.
Signed-off-by: Yosuke Iwamatsu <y-iwamatsu@xxxxxxxxxxxxx>
---
drivers/xen/pciback/xenbus.c | 51 ++++++++++++++++++++++++++++--------------
drivers/xen/pcifront/xenbus.c | 41 +++++++++++++++++----------------
2 files changed, 56 insertions(+), 36 deletions(-)
diff -r bd4b58143713 -r 5644f68a7912 drivers/xen/pciback/xenbus.c
--- a/drivers/xen/pciback/xenbus.c Wed Jul 16 11:19:14 2008 +0100
+++ b/drivers/xen/pciback/xenbus.c Wed Jul 16 13:51:36 2008 +0100
@@ -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:
diff -r bd4b58143713 -r 5644f68a7912 drivers/xen/pcifront/xenbus.c
--- a/drivers/xen/pcifront/xenbus.c Wed Jul 16 11:19:14 2008 +0100
+++ b/drivers/xen/pcifront/xenbus.c Wed Jul 16 13:51:36 2008 +0100
@@ -207,12 +207,17 @@ static int pcifront_try_disconnect(struc
prev_state = xenbus_read_driver_state(pdev->xdev->nodename);
- if (prev_state < XenbusStateClosing)
- err = xenbus_switch_state(pdev->xdev, XenbusStateClosing);
-
- if (!err && prev_state == XenbusStateConnected)
+ if (prev_state >= XenbusStateClosing)
+ goto out;
+
+ if(prev_state == XenbusStateConnected) {
+ pcifront_free_roots(pdev);
pcifront_disconnect(pdev);
-
+ }
+
+ err = xenbus_switch_state(pdev->xdev, XenbusStateClosed);
+
+ out:
spin_unlock(&pdev->dev_lock);
return err;
@@ -370,32 +375,28 @@ static void __init_refok pcifront_backen
struct pcifront_device *pdev = xdev->dev.driver_data;
switch (be_state) {
+ case XenbusStateUnknown:
+ case XenbusStateInitialising:
+ case XenbusStateInitWait:
+ case XenbusStateInitialised:
+ case XenbusStateClosed:
+ break;
+
+ case XenbusStateConnected:
+ pcifront_try_connect(pdev);
+ break;
+
case XenbusStateClosing:
dev_warn(&xdev->dev, "backend going away!\n");
pcifront_try_disconnect(pdev);
break;
- case XenbusStateUnknown:
- case XenbusStateClosed:
- dev_warn(&xdev->dev, "backend went away!\n");
- pcifront_try_disconnect(pdev);
-
- device_unregister(&pdev->xdev->dev);
- break;
-
- case XenbusStateConnected:
- pcifront_try_connect(pdev);
- break;
-
case XenbusStateReconfiguring:
pcifront_detach_devices(pdev);
break;
case XenbusStateReconfigured:
pcifront_attach_devices(pdev);
- break;
-
- default:
break;
}
}
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|