[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [linux-2.6.18-xen] pcifront/back: Fix handling of device disconnect.



# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.