ia64/linux-2.6.18-xen.hg

changeset 856:e5d3f2fa3428

netfront accel: Better watch handling across suspend/resume

Signed-off-by: Kieran Mansley <kmansley@solarflare.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Apr 07 10:29:30 2009 +0100 (2009-04-07)
parents 950b9eb27661
children a3ad7a5f2dcd
files drivers/xen/netfront/accel.c
line diff
     1.1 --- a/drivers/xen/netfront/accel.c	Mon Apr 06 13:51:20 2009 +0100
     1.2 +++ b/drivers/xen/netfront/accel.c	Tue Apr 07 10:29:30 2009 +0100
     1.3 @@ -51,6 +51,8 @@ static int netfront_load_accelerator(str
     1.4  				     struct xenbus_device *dev, 
     1.5  				     const char *frontend);
     1.6  
     1.7 +static void netfront_accelerator_remove_watch(struct netfront_info *np);
     1.8 +
     1.9  /*
    1.10   * List of all netfront accelerator plugin modules available.  Each
    1.11   * list entry is of type struct netfront_accelerator.
    1.12 @@ -164,8 +166,11 @@ void netfront_accelerator_add_watch(stru
    1.13  {
    1.14  	int err;
    1.15  	
    1.16 -	/* Check we're not trying to overwrite an existing watch */
    1.17 -	BUG_ON(np->accel_vif_state.accel_watch.node != NULL);
    1.18 +	/* 
    1.19 +	 * If old watch exists, e.g. from before suspend/resume,
    1.20 +	 * remove it now 
    1.21 +	 */
    1.22 +	netfront_accelerator_remove_watch(np);
    1.23  
    1.24  	/* Get a watch on the accelerator plugin */
    1.25  	err = xenbus_watch_path2(np->xbdev, np->xbdev->otherend, 
    1.26 @@ -180,6 +185,19 @@ void netfront_accelerator_add_watch(stru
    1.27  }
    1.28  
    1.29  
    1.30 +static void 
    1.31 +netfront_accelerator_purge_watch(struct netfront_accel_vif_state *vif_state)
    1.32 +{
    1.33 +	flush_workqueue(accel_watch_workqueue);
    1.34 +
    1.35 +	/* Clean up any state left from watch */
    1.36 +	if (vif_state->accel_frontend != NULL) {
    1.37 +		kfree(vif_state->accel_frontend);
    1.38 +		vif_state->accel_frontend = NULL;
    1.39 +	}
    1.40 +}
    1.41 +
    1.42 +
    1.43  static
    1.44  void netfront_accelerator_remove_watch(struct netfront_info *np)
    1.45  {
    1.46 @@ -191,13 +209,7 @@ void netfront_accelerator_remove_watch(s
    1.47  		kfree(vif_state->accel_watch.node);
    1.48  		vif_state->accel_watch.node = NULL;
    1.49  
    1.50 -		flush_workqueue(accel_watch_workqueue);
    1.51 -
    1.52 -		/* Clean up any state left from watch */
    1.53 -		if (vif_state->accel_frontend != NULL) {
    1.54 -			kfree(vif_state->accel_frontend);
    1.55 -			vif_state->accel_frontend = NULL;
    1.56 -		}
    1.57 +		netfront_accelerator_purge_watch(vif_state);
    1.58  	}	
    1.59  }
    1.60  
    1.61 @@ -670,8 +682,6 @@ int netfront_accelerator_suspend(struct 
    1.62  {
    1.63  	int rc = 0;
    1.64  	
    1.65 -	netfront_accelerator_remove_watch(np);
    1.66 -
    1.67  	mutex_lock(&accelerator_mutex);
    1.68  
    1.69   	/* Check that we've got a device that was accelerated */
    1.70 @@ -692,13 +702,16 @@ int netfront_accelerator_suspend(struct 
    1.71  int netfront_accelerator_suspend_cancel(struct netfront_info *np,
    1.72   					struct xenbus_device *dev)
    1.73  {
    1.74 +	netfront_accelerator_purge_watch(&np->accel_vif_state);
    1.75 +
    1.76  	/* 
    1.77 -	 * Setting the watch will cause it to fire and probe the
    1.78 -	 * accelerator, so no need to call accelerator_probe_new_vif()
    1.79 -	 * directly here
    1.80 +	 * Gratuitously fire the watch handler to reinstate the
    1.81 +	 * configured accelerator
    1.82  	 */
    1.83  	if (dev->state == XenbusStateConnected)
    1.84 -		netfront_accelerator_add_watch(np);
    1.85 +		queue_work(accel_watch_workqueue, 
    1.86 +			   &np->accel_vif_state.accel_work);
    1.87 +
    1.88  	return 0;
    1.89  }
    1.90