ia64/linux-2.6.18-xen.hg

changeset 604:5644f68a7912

pcifront/back: Fix handling of device disconnect.

Signed-off-by: Yosuke Iwamatsu <y-iwamatsu@ab.jp.nec.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jul 16 13:51:36 2008 +0100 (2008-07-16)
parents bd4b58143713
children 2d2436c48e43
files drivers/xen/pciback/xenbus.c drivers/xen/pcifront/xenbus.c
line diff
     1.1 --- a/drivers/xen/pciback/xenbus.c	Wed Jul 16 11:19:14 2008 +0100
     1.2 +++ b/drivers/xen/pciback/xenbus.c	Wed Jul 16 13:51:36 2008 +0100
     1.3 @@ -42,22 +42,35 @@ static struct pciback_device *alloc_pdev
     1.4  	return pdev;
     1.5  }
     1.6  
     1.7 -static void free_pdev(struct pciback_device *pdev)
     1.8 +static void pciback_disconnect(struct pciback_device *pdev)
     1.9  {
    1.10 -	if (pdev->be_watching)
    1.11 -		unregister_xenbus_watch(&pdev->be_watch);
    1.12 +	spin_lock(&pdev->dev_lock);
    1.13  
    1.14  	/* Ensure the guest can't trigger our handler before removing devices */
    1.15 -	if (pdev->evtchn_irq != INVALID_EVTCHN_IRQ)
    1.16 +	if (pdev->evtchn_irq != INVALID_EVTCHN_IRQ) {
    1.17  		unbind_from_irqhandler(pdev->evtchn_irq, pdev);
    1.18 +		pdev->evtchn_irq = INVALID_EVTCHN_IRQ;
    1.19 +	}
    1.20  
    1.21  	/* If the driver domain started an op, make sure we complete it or
    1.22  	 * delete it before releasing the shared memory */
    1.23  	cancel_delayed_work(&pdev->op_work);
    1.24  	flush_scheduled_work();
    1.25  
    1.26 -	if (pdev->sh_info)
    1.27 +	if (pdev->sh_info != NULL) {
    1.28  		xenbus_unmap_ring_vfree(pdev->xdev, pdev->sh_area);
    1.29 +		pdev->sh_info = NULL;
    1.30 +	}
    1.31 +
    1.32 +	spin_unlock(&pdev->dev_lock);
    1.33 +}
    1.34 +
    1.35 +static void free_pdev(struct pciback_device *pdev)
    1.36 +{
    1.37 +	if (pdev->be_watching)
    1.38 +		unregister_xenbus_watch(&pdev->be_watch);
    1.39 +
    1.40 +	pciback_disconnect(pdev);
    1.41  
    1.42  	pciback_release_devices(pdev);
    1.43  
    1.44 @@ -471,16 +484,6 @@ static void pciback_frontend_changed(str
    1.45  		pciback_attach(pdev);
    1.46  		break;
    1.47  
    1.48 -	case XenbusStateClosing:
    1.49 -		xenbus_switch_state(xdev, XenbusStateClosed);
    1.50 -		break;
    1.51 -
    1.52 -	case XenbusStateUnknown:
    1.53 -	case XenbusStateClosed:
    1.54 -		dev_dbg(&xdev->dev, "frontend is gone! unregister device\n");
    1.55 -		device_unregister(&xdev->dev);
    1.56 -		break;
    1.57 -
    1.58  	case XenbusStateReconfiguring:
    1.59  		pciback_reconfigure(pdev);
    1.60  		break;
    1.61 @@ -492,6 +495,22 @@ static void pciback_frontend_changed(str
    1.62  		xenbus_switch_state(xdev, XenbusStateConnected);
    1.63  		break;
    1.64  
    1.65 +	case XenbusStateClosing:
    1.66 +		pciback_disconnect(pdev);
    1.67 +		xenbus_switch_state(xdev, XenbusStateClosing);
    1.68 +		break;
    1.69 +
    1.70 +	case XenbusStateClosed:
    1.71 +		pciback_disconnect(pdev);
    1.72 +		xenbus_switch_state(xdev, XenbusStateClosed);
    1.73 +		if (xenbus_dev_is_online(xdev))
    1.74 +			break;
    1.75 +		/* fall through if not online */
    1.76 +	case XenbusStateUnknown:
    1.77 +		dev_dbg(&xdev->dev, "frontend is gone! unregister device\n");
    1.78 +		device_unregister(&xdev->dev);
    1.79 +		break;
    1.80 +
    1.81  	default:
    1.82  		break;
    1.83  	}
     2.1 --- a/drivers/xen/pcifront/xenbus.c	Wed Jul 16 11:19:14 2008 +0100
     2.2 +++ b/drivers/xen/pcifront/xenbus.c	Wed Jul 16 13:51:36 2008 +0100
     2.3 @@ -207,12 +207,17 @@ static int pcifront_try_disconnect(struc
     2.4  
     2.5  	prev_state = xenbus_read_driver_state(pdev->xdev->nodename);
     2.6  
     2.7 -	if (prev_state < XenbusStateClosing)
     2.8 -		err = xenbus_switch_state(pdev->xdev, XenbusStateClosing);
     2.9 +	if (prev_state >= XenbusStateClosing)
    2.10 +		goto out;
    2.11  
    2.12 -	if (!err && prev_state == XenbusStateConnected)
    2.13 +	if(prev_state == XenbusStateConnected) {
    2.14 +		pcifront_free_roots(pdev);
    2.15  		pcifront_disconnect(pdev);
    2.16 +	}
    2.17  
    2.18 +	err = xenbus_switch_state(pdev->xdev, XenbusStateClosed);
    2.19 +
    2.20 +      out:
    2.21  	spin_unlock(&pdev->dev_lock);
    2.22  
    2.23  	return err;
    2.24 @@ -370,23 +375,22 @@ static void __init_refok pcifront_backen
    2.25  	struct pcifront_device *pdev = xdev->dev.driver_data;
    2.26  
    2.27  	switch (be_state) {
    2.28 -	case XenbusStateClosing:
    2.29 -		dev_warn(&xdev->dev, "backend going away!\n");
    2.30 -		pcifront_try_disconnect(pdev);
    2.31 -		break;
    2.32 -
    2.33  	case XenbusStateUnknown:
    2.34 +	case XenbusStateInitialising:
    2.35 +	case XenbusStateInitWait:
    2.36 +	case XenbusStateInitialised:
    2.37  	case XenbusStateClosed:
    2.38 -		dev_warn(&xdev->dev, "backend went away!\n");
    2.39 -		pcifront_try_disconnect(pdev);
    2.40 -
    2.41 -		device_unregister(&pdev->xdev->dev);
    2.42  		break;
    2.43  
    2.44  	case XenbusStateConnected:
    2.45  		pcifront_try_connect(pdev);
    2.46  		break;
    2.47  
    2.48 +	case XenbusStateClosing:
    2.49 +		dev_warn(&xdev->dev, "backend going away!\n");
    2.50 +		pcifront_try_disconnect(pdev);
    2.51 +		break;
    2.52 +
    2.53  	case XenbusStateReconfiguring:
    2.54  		pcifront_detach_devices(pdev);
    2.55  		break;
    2.56 @@ -394,9 +398,6 @@ static void __init_refok pcifront_backen
    2.57  	case XenbusStateReconfigured:
    2.58  		pcifront_attach_devices(pdev);
    2.59  		break;
    2.60 -
    2.61 -	default:
    2.62 -		break;
    2.63  	}
    2.64  }
    2.65