ia64/linux-2.6.18-xen.hg

changeset 848:ab1d4fbbe4bf

netfront accel: Simplify, document, and fix a theoretical bug in use
of spin locks by netfront acceleration plugins

Signed-off-by: Kieran Mansley <kmansley@solarflare.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Mar 31 12:00:03 2009 +0100 (2009-03-31)
parents ad4d307bf9ce
children 3a4410c4504e
files drivers/xen/netfront/accel.c drivers/xen/netfront/netfront.c
line diff
     1.1 --- a/drivers/xen/netfront/accel.c	Tue Mar 31 11:59:10 2009 +0100
     1.2 +++ b/drivers/xen/netfront/accel.c	Tue Mar 31 12:00:03 2009 +0100
     1.3 @@ -57,9 +57,6 @@ static int netfront_load_accelerator(str
     1.4   */ 
     1.5  static struct list_head accelerators_list;
     1.6  
     1.7 -/* Lock to protect access to accelerators_list */
     1.8 -static spinlock_t accelerators_lock;
     1.9 -
    1.10  /* Workqueue to process acceleration configuration changes */
    1.11  struct workqueue_struct *accel_watch_workqueue;
    1.12  
    1.13 @@ -69,7 +66,6 @@ DEFINE_MUTEX(accelerator_mutex);
    1.14  void netif_init_accel(void)
    1.15  {
    1.16  	INIT_LIST_HEAD(&accelerators_list);
    1.17 -	spin_lock_init(&accelerators_lock);
    1.18  
    1.19  	accel_watch_workqueue = create_workqueue("net_accel");
    1.20  }
    1.21 @@ -77,13 +73,11 @@ void netif_init_accel(void)
    1.22  void netif_exit_accel(void)
    1.23  {
    1.24  	struct netfront_accelerator *accelerator, *tmp;
    1.25 -	unsigned long flags;
    1.26  
    1.27  	flush_workqueue(accel_watch_workqueue);
    1.28  	destroy_workqueue(accel_watch_workqueue);
    1.29  
    1.30 -	spin_lock_irqsave(&accelerators_lock, flags);
    1.31 -
    1.32 +	/* No lock required as everything else should be quiet by now */
    1.33  	list_for_each_entry_safe(accelerator, tmp, &accelerators_list, link) {
    1.34  		BUG_ON(!list_empty(&accelerator->vif_states));
    1.35  
    1.36 @@ -91,8 +85,6 @@ void netif_exit_accel(void)
    1.37  		kfree(accelerator->frontend);
    1.38  		kfree(accelerator);
    1.39  	}
    1.40 -
    1.41 -	spin_unlock_irqrestore(&accelerators_lock, flags);
    1.42  }
    1.43  
    1.44  
    1.45 @@ -245,16 +237,12 @@ static int match_accelerator(const char 
    1.46  
    1.47  /* 
    1.48   * Add a frontend vif to the list of vifs that is using a netfront
    1.49 - * accelerator plugin module.
    1.50 + * accelerator plugin module.  Must be called with the accelerator
    1.51 + * mutex held.
    1.52   */
    1.53  static void add_accelerator_vif(struct netfront_accelerator *accelerator,
    1.54  				struct netfront_info *np)
    1.55  {
    1.56 -	unsigned long flags;
    1.57 -
    1.58 -	/* Need lock to write list */
    1.59 -	spin_lock_irqsave(&accelerator->vif_states_lock, flags);
    1.60 -
    1.61  	if (np->accelerator == NULL) {
    1.62  		np->accelerator = accelerator;
    1.63  		
    1.64 @@ -267,13 +255,13 @@ static void add_accelerator_vif(struct n
    1.65  		 */
    1.66  		BUG_ON(np->accelerator != accelerator);
    1.67  	}
    1.68 -
    1.69 -	spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
    1.70  }
    1.71  
    1.72  
    1.73  /*
    1.74 - * Initialise the state to track an accelerator plugin module.
    1.75 + * Initialise the state to track an accelerator plugin module.  
    1.76 + * 
    1.77 + * Must be called with the accelerator mutex held.
    1.78   */ 
    1.79  static int init_accelerator(const char *frontend, 
    1.80  			    struct netfront_accelerator **result,
    1.81 @@ -281,7 +269,6 @@ static int init_accelerator(const char *
    1.82  {
    1.83  	struct netfront_accelerator *accelerator = 
    1.84  		kmalloc(sizeof(struct netfront_accelerator), GFP_KERNEL);
    1.85 -	unsigned long flags;
    1.86  	int frontend_len;
    1.87  
    1.88  	if (!accelerator) {
    1.89 @@ -303,9 +290,7 @@ static int init_accelerator(const char *
    1.90  
    1.91  	accelerator->hooks = hooks;
    1.92  
    1.93 -	spin_lock_irqsave(&accelerators_lock, flags);
    1.94  	list_add(&accelerator->link, &accelerators_list);
    1.95 -	spin_unlock_irqrestore(&accelerators_lock, flags);
    1.96  
    1.97  	*result = accelerator;
    1.98  
    1.99 @@ -316,11 +301,14 @@ static int init_accelerator(const char *
   1.100  /* 
   1.101   * Modify the hooks stored in the per-vif state to match that in the
   1.102   * netfront accelerator's state.
   1.103 + * 
   1.104 + * Takes the vif_states_lock spinlock and may sleep.
   1.105   */
   1.106  static void 
   1.107  accelerator_set_vif_state_hooks(struct netfront_accel_vif_state *vif_state)
   1.108  {
   1.109 -	/* This function must be called with the vif_states_lock held */
   1.110 +	struct netfront_accelerator *accelerator;
   1.111 +	unsigned long flags;
   1.112  
   1.113  	DPRINTK("%p\n",vif_state);
   1.114  
   1.115 @@ -328,19 +316,25 @@ accelerator_set_vif_state_hooks(struct n
   1.116  	netif_poll_disable(vif_state->np->netdev);
   1.117  	netif_tx_lock_bh(vif_state->np->netdev);
   1.118  
   1.119 -	vif_state->hooks = vif_state->np->accelerator->hooks;
   1.120 +	accelerator = vif_state->np->accelerator;
   1.121 +	spin_lock_irqsave(&accelerator->vif_states_lock, flags);
   1.122 +	vif_state->hooks = accelerator->hooks;
   1.123 +	spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
   1.124  
   1.125  	netif_tx_unlock_bh(vif_state->np->netdev);
   1.126  	netif_poll_enable(vif_state->np->netdev);
   1.127  }
   1.128  
   1.129  
   1.130 +/* 
   1.131 + * Must be called with the accelerator mutex held.  Takes the
   1.132 + * vif_states_lock spinlock.
   1.133 + */
   1.134  static void accelerator_probe_new_vif(struct netfront_info *np,
   1.135  				      struct xenbus_device *dev, 
   1.136  				      struct netfront_accelerator *accelerator)
   1.137  {
   1.138  	struct netfront_accel_hooks *hooks;
   1.139 -	unsigned long flags;
   1.140  
   1.141  	DPRINTK("\n");
   1.142  
   1.143 @@ -349,17 +343,8 @@ static void accelerator_probe_new_vif(st
   1.144  	
   1.145  	hooks = accelerator->hooks;
   1.146  	
   1.147 -	if (hooks) {
   1.148 -		if (hooks->new_device(np->netdev, dev) == 0) {
   1.149 -			spin_lock_irqsave
   1.150 -				(&accelerator->vif_states_lock, flags);
   1.151 -
   1.152 -			accelerator_set_vif_state_hooks(&np->accel_vif_state);
   1.153 -
   1.154 -			spin_unlock_irqrestore
   1.155 -				(&accelerator->vif_states_lock, flags);
   1.156 -		}
   1.157 -	}
   1.158 +	if (hooks && hooks->new_device(np->netdev, dev) == 0)
   1.159 +		accelerator_set_vif_state_hooks(&np->accel_vif_state);
   1.160  
   1.161  	return;
   1.162  }
   1.163 @@ -368,7 +353,10 @@ static void accelerator_probe_new_vif(st
   1.164  /*  
   1.165   * Request that a particular netfront accelerator plugin is loaded.
   1.166   * Usually called as a result of the vif configuration specifying
   1.167 - * which one to use. Must be called with accelerator_mutex held 
   1.168 + * which one to use.
   1.169 + *
   1.170 + * Must be called with accelerator_mutex held.  Takes the
   1.171 + * vif_states_lock spinlock.
   1.172   */
   1.173  static int netfront_load_accelerator(struct netfront_info *np, 
   1.174  				     struct xenbus_device *dev, 
   1.175 @@ -407,13 +395,15 @@ static int netfront_load_accelerator(str
   1.176   * this accelerator.  Notify the accelerator plugin of the relevant
   1.177   * device if so.  Called when an accelerator plugin module is first
   1.178   * loaded and connects to netfront.
   1.179 + *
   1.180 + * Must be called with accelerator_mutex held.  Takes the
   1.181 + * vif_states_lock spinlock.
   1.182   */
   1.183  static void 
   1.184  accelerator_probe_vifs(struct netfront_accelerator *accelerator,
   1.185  		       struct netfront_accel_hooks *hooks)
   1.186  {
   1.187  	struct netfront_accel_vif_state *vif_state, *tmp;
   1.188 -	unsigned long flags;
   1.189  
   1.190  	DPRINTK("%p\n", accelerator);
   1.191  
   1.192 @@ -425,29 +415,22 @@ accelerator_probe_vifs(struct netfront_a
   1.193  	BUG_ON(hooks == NULL);
   1.194  	accelerator->hooks = hooks;
   1.195  
   1.196 -	/* 
   1.197 -	 *  currently hold accelerator_mutex, so don't need
   1.198 -	 *  vif_states_lock to read the list
   1.199 -	 */
   1.200 +	/* Holds accelerator_mutex to iterate list */
   1.201  	list_for_each_entry_safe(vif_state, tmp, &accelerator->vif_states,
   1.202  				 link) {
   1.203  		struct netfront_info *np = vif_state->np;
   1.204  		
   1.205 -		if (hooks->new_device(np->netdev, vif_state->dev) == 0) {
   1.206 -			spin_lock_irqsave
   1.207 -				(&accelerator->vif_states_lock, flags);
   1.208 -
   1.209 +		if (hooks->new_device(np->netdev, vif_state->dev) == 0)
   1.210  			accelerator_set_vif_state_hooks(vif_state);
   1.211 -
   1.212 -			spin_unlock_irqrestore
   1.213 -				(&accelerator->vif_states_lock, flags);
   1.214 -		}
   1.215  	}
   1.216  }
   1.217  
   1.218  
   1.219  /* 
   1.220 - * Called by the netfront accelerator plugin module when it has loaded 
   1.221 + * Called by the netfront accelerator plugin module when it has
   1.222 + * loaded.
   1.223 + *
   1.224 + * Takes the accelerator_mutex and vif_states_lock spinlock.
   1.225   */
   1.226  int netfront_accelerator_loaded(int version, const char *frontend, 
   1.227  				struct netfront_accel_hooks *hooks)
   1.228 @@ -503,15 +486,21 @@ EXPORT_SYMBOL_GPL(netfront_accelerator_l
   1.229  
   1.230  /* 
   1.231   * Remove the hooks from a single vif state.
   1.232 + * 
   1.233 + * Takes the vif_states_lock spinlock and may sleep.
   1.234   */
   1.235  static void 
   1.236  accelerator_remove_single_hook(struct netfront_accelerator *accelerator,
   1.237  			       struct netfront_accel_vif_state *vif_state)
   1.238  {
   1.239 +	unsigned long flags;
   1.240 +
   1.241  	/* Make sure there are no data path operations going on */
   1.242  	netif_poll_disable(vif_state->np->netdev);
   1.243  	netif_tx_lock_bh(vif_state->np->netdev);
   1.244  
   1.245 +	spin_lock_irqsave(&accelerator->vif_states_lock, flags);
   1.246 +
   1.247  	/* 
   1.248  	 * Remove the hooks, but leave the vif_state on the
   1.249  	 * accelerator's list as that signifies this vif is
   1.250 @@ -520,6 +509,8 @@ accelerator_remove_single_hook(struct ne
   1.251  	 */
   1.252  	vif_state->hooks = NULL;
   1.253  	
   1.254 +	spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
   1.255 +
   1.256  	netif_tx_unlock_bh(vif_state->np->netdev);
   1.257  	netif_poll_enable(vif_state->np->netdev);		       
   1.258  }
   1.259 @@ -527,25 +518,25 @@ accelerator_remove_single_hook(struct ne
   1.260  
   1.261  /* 
   1.262   * Safely remove the accelerator function hooks from a netfront state.
   1.263 + * 
   1.264 + * Must be called with the accelerator mutex held.  Takes the
   1.265 + * vif_states_lock spinlock.
   1.266   */
   1.267  static void accelerator_remove_hooks(struct netfront_accelerator *accelerator)
   1.268  {
   1.269 -	struct netfront_accel_hooks *hooks;
   1.270  	struct netfront_accel_vif_state *vif_state, *tmp;
   1.271  	unsigned long flags;
   1.272  
   1.273 -	/* Mutex is held so don't need vif_states_lock to iterate list */
   1.274 +	/* Mutex is held to iterate list */
   1.275  	list_for_each_entry_safe(vif_state, tmp,
   1.276  				 &accelerator->vif_states,
   1.277  				 link) {
   1.278 -		spin_lock_irqsave(&accelerator->vif_states_lock, flags);
   1.279 -
   1.280  		if(vif_state->hooks) {
   1.281 -			hooks = vif_state->hooks;
   1.282 -			
   1.283 +			spin_lock_irqsave(&accelerator->vif_states_lock, flags);
   1.284 +
   1.285  			/* Last chance to get statistics from the accelerator */
   1.286 -			hooks->get_stats(vif_state->np->netdev,
   1.287 -					 &vif_state->np->stats);
   1.288 +			vif_state->hooks->get_stats(vif_state->np->netdev,
   1.289 +						    &vif_state->np->stats);
   1.290  
   1.291  			spin_unlock_irqrestore(&accelerator->vif_states_lock,
   1.292  					       flags);
   1.293 @@ -553,9 +544,6 @@ static void accelerator_remove_hooks(str
   1.294  			accelerator_remove_single_hook(accelerator, vif_state);
   1.295  
   1.296  			accelerator->hooks->remove(vif_state->dev);
   1.297 -		} else {
   1.298 -			spin_unlock_irqrestore(&accelerator->vif_states_lock,
   1.299 -					       flags);
   1.300  		}
   1.301  	}
   1.302  	
   1.303 @@ -567,47 +555,47 @@ static void accelerator_remove_hooks(str
   1.304   * Called by a netfront accelerator when it is unloaded.  This safely
   1.305   * removes the hooks into the plugin and blocks until all devices have
   1.306   * finished using it, so on return it is safe to unload.
   1.307 + *
   1.308 + * Takes the accelerator mutex, and vif_states_lock spinlock.
   1.309   */
   1.310  void netfront_accelerator_stop(const char *frontend)
   1.311  {
   1.312  	struct netfront_accelerator *accelerator;
   1.313 -	unsigned long flags;
   1.314  
   1.315  	mutex_lock(&accelerator_mutex);
   1.316 -	spin_lock_irqsave(&accelerators_lock, flags);
   1.317  
   1.318  	list_for_each_entry(accelerator, &accelerators_list, link) {
   1.319  		if (match_accelerator(frontend, accelerator)) {
   1.320 -			spin_unlock_irqrestore(&accelerators_lock, flags);
   1.321 -
   1.322  			accelerator_remove_hooks(accelerator);
   1.323 -
   1.324  			goto out;
   1.325  		}
   1.326  	}
   1.327 -	spin_unlock_irqrestore(&accelerators_lock, flags);
   1.328   out:
   1.329  	mutex_unlock(&accelerator_mutex);
   1.330  }
   1.331  EXPORT_SYMBOL_GPL(netfront_accelerator_stop);
   1.332  
   1.333  
   1.334 -/* Helper for call_remove and do_suspend */
   1.335 -static int do_remove(struct netfront_info *np, struct xenbus_device *dev,
   1.336 -		     unsigned long *lock_flags)
   1.337 +/* 
   1.338 + * Helper for call_remove and do_suspend
   1.339 + * 
   1.340 + * Must be called with the accelerator mutex held.  Takes the
   1.341 + * vif_states_lock spinlock.
   1.342 + */
   1.343 +static int do_remove(struct netfront_info *np, struct xenbus_device *dev)
   1.344  {
   1.345  	struct netfront_accelerator *accelerator = np->accelerator;
   1.346 - 	struct netfront_accel_hooks *hooks;
   1.347 +	unsigned long flags;
   1.348   	int rc = 0;
   1.349   
   1.350  	if (np->accel_vif_state.hooks) {
   1.351 -		hooks = np->accel_vif_state.hooks;
   1.352 +		spin_lock_irqsave(&accelerator->vif_states_lock, flags);
   1.353  
   1.354  		/* Last chance to get statistics from the accelerator */
   1.355 -		hooks->get_stats(np->netdev, &np->stats);
   1.356 +		np->accel_vif_state.hooks->get_stats(np->netdev, &np->stats);
   1.357  
   1.358  		spin_unlock_irqrestore(&accelerator->vif_states_lock, 
   1.359 -				       *lock_flags);
   1.360 +				       flags);
   1.361  
   1.362   		/* 
   1.363   		 * Try and do the opposite of accelerator_probe_new_vif
   1.364 @@ -618,20 +606,21 @@ static int do_remove(struct netfront_inf
   1.365   					       &np->accel_vif_state);
   1.366  
   1.367  		rc = accelerator->hooks->remove(dev);
   1.368 -
   1.369 -		spin_lock_irqsave(&accelerator->vif_states_lock, *lock_flags);
   1.370  	}
   1.371   
   1.372   	return rc;
   1.373  }
   1.374  
   1.375  
   1.376 +/*
   1.377 + * Must be called with the accelerator mutex held.  Takes the
   1.378 + * vif_states_lock spinlock
   1.379 + */
   1.380  static int netfront_remove_accelerator(struct netfront_info *np,
   1.381  				       struct xenbus_device *dev)
   1.382  {
   1.383  	struct netfront_accelerator *accelerator;
   1.384   	struct netfront_accel_vif_state *tmp_vif_state;
   1.385 -  	unsigned long flags;
   1.386  	int rc = 0; 
   1.387  
   1.388   	/* Check that we've got a device that was accelerated */
   1.389 @@ -640,8 +629,6 @@ static int netfront_remove_accelerator(s
   1.390  
   1.391  	accelerator = np->accelerator;
   1.392  
   1.393 -	spin_lock_irqsave(&accelerator->vif_states_lock, flags); 
   1.394 -
   1.395  	list_for_each_entry(tmp_vif_state, &accelerator->vif_states,
   1.396  			    link) {
   1.397  		if (tmp_vif_state == &np->accel_vif_state) {
   1.398 @@ -650,16 +637,18 @@ static int netfront_remove_accelerator(s
   1.399  		}
   1.400  	}
   1.401  
   1.402 -	rc = do_remove(np, dev, &flags);
   1.403 +	rc = do_remove(np, dev);
   1.404  
   1.405  	np->accelerator = NULL;
   1.406  
   1.407 -	spin_unlock_irqrestore(&accelerator->vif_states_lock, flags); 
   1.408 -
   1.409  	return rc;
   1.410  }
   1.411  
   1.412  
   1.413 +/*
   1.414 + * No lock pre-requisites.  Takes the accelerator mutex and the
   1.415 + * vif_states_lock spinlock.
   1.416 + */
   1.417  int netfront_accelerator_call_remove(struct netfront_info *np,
   1.418  				     struct xenbus_device *dev)
   1.419  {
   1.420 @@ -671,11 +660,14 @@ int netfront_accelerator_call_remove(str
   1.421  	return rc;
   1.422  }
   1.423  
   1.424 -  
   1.425 +
   1.426 +/*
   1.427 + * No lock pre-requisites.  Takes the accelerator mutex and the
   1.428 + * vif_states_lock spinlock.
   1.429 + */
   1.430  int netfront_accelerator_suspend(struct netfront_info *np,
   1.431   				 struct xenbus_device *dev)
   1.432  {
   1.433 -	unsigned long flags;
   1.434  	int rc = 0;
   1.435  	
   1.436  	netfront_accelerator_remove_watch(np);
   1.437 @@ -690,11 +682,7 @@ int netfront_accelerator_suspend(struct 
   1.438  	 * Call the remove accelerator hook, but leave the vif_state
   1.439  	 * on the accelerator's list in case there is a suspend_cancel.
   1.440  	 */
   1.441 -	spin_lock_irqsave(&np->accelerator->vif_states_lock, flags); 
   1.442 -	
   1.443 -	rc = do_remove(np, dev, &flags);
   1.444 -
   1.445 -	spin_unlock_irqrestore(&np->accelerator->vif_states_lock, flags); 
   1.446 +	rc = do_remove(np, dev);
   1.447   out:
   1.448  	mutex_unlock(&accelerator_mutex);
   1.449  	return rc;
   1.450 @@ -713,15 +701,16 @@ int netfront_accelerator_suspend_cancel(
   1.451  		netfront_accelerator_add_watch(np);
   1.452  	return 0;
   1.453  }
   1.454 - 
   1.455 - 
   1.456 +
   1.457 +
   1.458 +/*
   1.459 + * No lock pre-requisites.  Takes the accelerator mutex
   1.460 + */
   1.461  void netfront_accelerator_resume(struct netfront_info *np,
   1.462   				 struct xenbus_device *dev)
   1.463  {
   1.464   	struct netfront_accel_vif_state *accel_vif_state = NULL;
   1.465 - 	spinlock_t *vif_states_lock;
   1.466 - 	unsigned long flags;
   1.467 - 
   1.468 +
   1.469   	mutex_lock(&accelerator_mutex);
   1.470  
   1.471  	/* Check that we've got a device that was accelerated */
   1.472 @@ -734,9 +723,6 @@ void netfront_accelerator_resume(struct 
   1.473   		if (accel_vif_state->dev == dev) {
   1.474   			BUG_ON(accel_vif_state != &np->accel_vif_state);
   1.475   
   1.476 - 			vif_states_lock = &np->accelerator->vif_states_lock;
   1.477 -			spin_lock_irqsave(vif_states_lock, flags); 
   1.478 - 
   1.479   			/* 
   1.480   			 * Remove it from the accelerator's list so
   1.481   			 * state is consistent for probing new vifs
   1.482 @@ -744,9 +730,7 @@ void netfront_accelerator_resume(struct 
   1.483   			 */
   1.484   			list_del(&accel_vif_state->link);
   1.485   			np->accelerator = NULL;
   1.486 - 
   1.487 - 			spin_unlock_irqrestore(vif_states_lock, flags); 
   1.488 - 			
   1.489 +
   1.490  			break;
   1.491   		}
   1.492   	}
   1.493 @@ -757,11 +741,13 @@ void netfront_accelerator_resume(struct 
   1.494  }
   1.495  
   1.496  
   1.497 +/*
   1.498 + * No lock pre-requisites.  Takes the vif_states_lock spinlock
   1.499 + */
   1.500  int netfront_check_accelerator_queue_ready(struct net_device *dev,
   1.501  					   struct netfront_info *np)
   1.502  {
   1.503  	struct netfront_accelerator *accelerator;
   1.504 -	struct netfront_accel_hooks *hooks;
   1.505  	int rc = 1;
   1.506  	unsigned long flags;
   1.507  
   1.508 @@ -770,8 +756,8 @@ int netfront_check_accelerator_queue_rea
   1.509  	/* Call the check_ready accelerator hook. */ 
   1.510  	if (np->accel_vif_state.hooks && accelerator) {
   1.511  		spin_lock_irqsave(&accelerator->vif_states_lock, flags); 
   1.512 -		hooks = np->accel_vif_state.hooks;
   1.513 -		if (hooks && np->accelerator == accelerator)
   1.514 +		if (np->accel_vif_state.hooks &&
   1.515 +		    np->accelerator == accelerator)
   1.516  			rc = np->accel_vif_state.hooks->check_ready(dev);
   1.517  		spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
   1.518  	}
   1.519 @@ -780,11 +766,13 @@ int netfront_check_accelerator_queue_rea
   1.520  }
   1.521  
   1.522  
   1.523 +/*
   1.524 + * No lock pre-requisites.  Takes the vif_states_lock spinlock
   1.525 + */
   1.526  void netfront_accelerator_call_stop_napi_irq(struct netfront_info *np,
   1.527  					     struct net_device *dev)
   1.528  {
   1.529  	struct netfront_accelerator *accelerator;
   1.530 -	struct netfront_accel_hooks *hooks;
   1.531  	unsigned long flags;
   1.532  
   1.533  	accelerator = np->accelerator;
   1.534 @@ -792,19 +780,21 @@ void netfront_accelerator_call_stop_napi
   1.535  	/* Call the stop_napi_interrupts accelerator hook. */
   1.536  	if (np->accel_vif_state.hooks && accelerator != NULL) {
   1.537  		spin_lock_irqsave(&accelerator->vif_states_lock, flags); 
   1.538 -		hooks = np->accel_vif_state.hooks;
   1.539 -		if (hooks && np->accelerator == accelerator)
   1.540 +		if (np->accel_vif_state.hooks &&
   1.541 +		    np->accelerator == accelerator)
   1.542   			np->accel_vif_state.hooks->stop_napi_irq(dev);
   1.543  		spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
   1.544  	}
   1.545  }
   1.546  
   1.547  
   1.548 +/*
   1.549 + * No lock pre-requisites.  Takes the vif_states_lock spinlock
   1.550 + */
   1.551  int netfront_accelerator_call_get_stats(struct netfront_info *np,
   1.552  					struct net_device *dev)
   1.553  {
   1.554  	struct netfront_accelerator *accelerator;
   1.555 -	struct netfront_accel_hooks *hooks;
   1.556  	unsigned long flags;
   1.557  	int rc = 0;
   1.558  
   1.559 @@ -813,8 +803,8 @@ int netfront_accelerator_call_get_stats(
   1.560  	/* Call the get_stats accelerator hook. */
   1.561  	if (np->accel_vif_state.hooks && accelerator != NULL) {
   1.562  		spin_lock_irqsave(&accelerator->vif_states_lock, flags); 
   1.563 -		hooks = np->accel_vif_state.hooks;
   1.564 -		if (hooks && np->accelerator == accelerator)
   1.565 +		if (np->accel_vif_state.hooks && 
   1.566 +		    np->accelerator == accelerator)
   1.567   			rc = np->accel_vif_state.hooks->get_stats(dev,
   1.568  								  &np->stats);
   1.569  		spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
     2.1 --- a/drivers/xen/netfront/netfront.c	Tue Mar 31 11:59:10 2009 +0100
     2.2 +++ b/drivers/xen/netfront/netfront.c	Tue Mar 31 12:00:03 2009 +0100
     2.3 @@ -2238,10 +2238,9 @@ static void __exit netif_exit(void)
     2.4  #ifdef CONFIG_INET
     2.5  	unregister_inetaddr_notifier(&notifier_inetdev);
     2.6  #endif
     2.7 +	xenbus_unregister_driver(&netfront_driver);
     2.8  
     2.9  	netif_exit_accel();
    2.10 -
    2.11 -	return xenbus_unregister_driver(&netfront_driver);
    2.12  }
    2.13  module_exit(netif_exit);
    2.14