]> xenbits.xensource.com Git - xenclient/kernel.git/commitdiff
netfront accel: Use remove and probe hooks rather than extra suspend
authorKeir Fraser <keir@xensource.com>
Tue, 30 Oct 2007 17:31:17 +0000 (17:31 +0000)
committerKeir Fraser <keir@xensource.com>
Tue, 30 Oct 2007 17:31:17 +0000 (17:31 +0000)
and resume hooks for acceleration.
Signed-off-by <kmansley@solarflare.com>

drivers/xen/netfront/accel.c
drivers/xen/netfront/netfront.c
drivers/xen/netfront/netfront.h

index cfe3a18ed161cb8e30cd9cfa09fa8b1c4f5e2123..9a2ca9e03c57377cc301b81aff6e2683b398d3d8 100644 (file)
@@ -118,9 +118,9 @@ static void add_accelerator_vif(struct netfront_accelerator *accelerator,
                list_add(&np->accel_vif_state.link, &accelerator->vif_states);
        } else {
                /* 
-                * May get here legitimately if reconnecting to the
-                * same accelerator, eg. after resume, so check that
-                * is the case
+                * May get here legitimately if suspend_cancel is
+                * called, but in that case configuration should not
+                * have changed
                 */
                BUG_ON(np->accelerator != accelerator);
        }
@@ -313,7 +313,7 @@ int netfront_load_accelerator(struct netfront_info *np,
 static void 
 accelerator_probe_vifs(struct netfront_accelerator *accelerator,
                       struct netfront_accel_hooks *hooks,
-                      unsigned lock_flags)
+                      unsigned *lock_flags)
 {
        struct netfront_accel_vif_state *vif_state, *tmp;
 
@@ -349,14 +349,15 @@ accelerator_probe_vifs(struct netfront_accelerator *accelerator,
                         * protected by the kref
                         */
                        spin_unlock_irqrestore(&accelerator->vif_states_lock,
-                                              lock_flags);
+                                              (*lock_flags));
                        
                        hooks->new_device(np->netdev, vif_state->dev);
                        
                        kref_put(&accelerator->accel_kref, accel_kref_release);
 
                        /* Retake lock for next go round the loop */
-                       spin_lock_irqsave(&accelerator->vif_states_lock, lock_flags);
+                       spin_lock_irqsave(&accelerator->vif_states_lock,
+                                         (*lock_flags));
                        
                        /*
                         * Hooks will get linked into vif_state by a call to
@@ -391,7 +392,7 @@ accelerator_probe_vifs_on_load(struct netfront_accelerator *accelerator,
        
        if (accelerator->ready_for_probe) {
                accelerator->ready_for_probe = 0;
-               accelerator_probe_vifs(accelerator, hooks, flags);
+               accelerator_probe_vifs(accelerator, hooks, &flags);
        } else {
                if (accelerator->need_probe)
                        DPRINTK("Probe request on accelerator awaiting probe\n");
@@ -526,8 +527,7 @@ accelerator_remove_single_hook(struct netfront_accelerator *accelerator,
 /* 
  * Safely remove the accelerator function hooks from a netfront state.
  */
-static void accelerator_remove_hooks(struct netfront_accelerator *accelerator,
-                                    int remove_master)
+static void accelerator_remove_hooks(struct netfront_accelerator *accelerator)
 {
        struct netfront_accel_hooks *hooks;
        struct netfront_accel_vif_state *vif_state, *tmp;
@@ -538,31 +538,33 @@ static void accelerator_remove_hooks(struct netfront_accelerator *accelerator,
        list_for_each_entry_safe(vif_state, tmp,
                                 &accelerator->vif_states,
                                 link) {
+               BUG_ON(vif_state->hooks == NULL);
                hooks = vif_state->hooks;
                accelerator_remove_single_hook(accelerator, vif_state);
 
-               /* 
-                * Remove the reference taken when the vif_state hooks
-                * were set, must be called without lock held
-                */
+               /* 
+                * Tell accelerator that this device is being removed,
+                * and remove the reference taken when the vif_state
+                * hooks were set; both must be called without lock
+                * held
+                */
                spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
 
                /* Last chance to get statistics from the accelerator */
                hooks->get_stats(vif_state->np->netdev, &vif_state->np->stats);
+               hooks->remove(vif_state->dev);
 
                kref_put(&vif_state->vif_kref, vif_kref_release);
 
                spin_lock_irqsave(&accelerator->vif_states_lock, flags);
        }
        
-       if(remove_master)
-               accelerator->hooks = NULL;
+       accelerator->hooks = NULL;
 
        spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
 
-       if(remove_master)
-               /* Remove the reference taken when module loaded */ 
-               kref_put(&accelerator->accel_kref, accel_kref_release);
+       /* Remove the reference taken when module loaded */ 
+       kref_put(&accelerator->accel_kref, accel_kref_release);
 }
 
 
@@ -571,7 +573,7 @@ static void accelerator_remove_hooks(struct netfront_accelerator *accelerator,
  * removes the hooks into the plugin and blocks until all devices have
  * finished using it, so on return it is safe to unload.
  */
-void netfront_accelerator_stop(const char *frontend, int unloading)
+void netfront_accelerator_stop(const char *frontend)
 {
        struct netfront_accelerator *accelerator;
        unsigned flags;
@@ -588,11 +590,10 @@ void netfront_accelerator_stop(const char *frontend, int unloading)
                         */
                        sema_init(&accelerator->exit_semaphore, 0);
 
-                       accelerator_remove_hooks(accelerator, unloading);
+                       accelerator_remove_hooks(accelerator);
 
-                       if (unloading)
-                               /* Wait for hooks to be unused, then return */
-                               down(&accelerator->exit_semaphore);
+                       /* Wait for hooks to be unused, then return */
+                       down(&accelerator->exit_semaphore);
                        
                        return;
                }
@@ -606,23 +607,26 @@ EXPORT_SYMBOL_GPL(netfront_accelerator_stop);
 int netfront_check_accelerator_queue_busy(struct net_device *dev,
                                          struct netfront_info *np)
 {
+       struct netfront_accelerator *accelerator;
        struct netfront_accel_hooks *hooks;
        int rc = 1;
        unsigned flags;
 
+       accelerator = np->accelerator;
+
        /*
         * Call the check busy accelerator hook. The use count for the
         * accelerator's hooks is incremented for the duration of the
         * call to prevent the accelerator being able to modify the
         * hooks in the middle (by, for example, unloading)
         */ 
-       if (np->accel_vif_state.hooks) {
-               spin_lock_irqsave(&np->accelerator->vif_states_lock, flags); 
+       if (np->accel_vif_state.hooks && accelerator) {
+               spin_lock_irqsave(&accelerator->vif_states_lock, flags); 
                hooks = np->accel_vif_state.hooks;
-               if (hooks) {
+               if (hooks && np->accelerator == accelerator) {
                        kref_get(&np->accel_vif_state.vif_kref);
                        spin_unlock_irqrestore
-                               (&np->accelerator->vif_states_lock, flags);
+                               (&accelerator->vif_states_lock, flags);
 
                        rc = np->accel_vif_state.hooks->check_busy(dev);
                        
@@ -630,7 +634,7 @@ int netfront_check_accelerator_queue_busy(struct net_device *dev,
                                 vif_kref_release);
                } else {
                        spin_unlock_irqrestore
-                               (&np->accelerator->vif_states_lock, flags);
+                               (&accelerator->vif_states_lock, flags);
                }
        }
 
@@ -638,180 +642,174 @@ int netfront_check_accelerator_queue_busy(struct net_device *dev,
 }
 
 
-int netfront_accelerator_call_remove(struct netfront_info *np,
-                                    struct xenbus_device *dev)
+/* Helper for call_remove and do_suspend */
+static int do_remove(struct netfront_info *np, struct xenbus_device *dev,
+                    unsigned lock_flags, int clear_accelerator)
 {
        struct netfront_accelerator *accelerator = np->accelerator;
-       struct netfront_accel_vif_state *tmp_vif_state;
-       struct netfront_accel_hooks *hooks;
+       struct netfront_accel_hooks *hooks;
        unsigned flags;
-       int rc = 0;
-
-       /* 
-        * Call the remove accelerator hook. The use count for the
-        * accelerator's hooks is incremented for the duration of the
-        * call to prevent the accelerator being able to modify the
-        * hooks in the middle (by, for example, unloading)
-        */ 
-       spin_lock_irqsave(&np->accelerator->vif_states_lock, flags); 
-       hooks = np->accel_vif_state.hooks;
+       int rc = 0;
+       if(clear_accelerator)
+               np->accelerator = NULL;
 
-       /*
-        * Remove this vif_state from the accelerator's list 
-        */
-       list_for_each_entry(tmp_vif_state, &accelerator->vif_states, link) {
-               if (tmp_vif_state == &np->accel_vif_state) {
-                       list_del(&np->accel_vif_state.link);
-                       break;
-               }
-       }
-          
-       if (hooks) {
-               kref_get(&np->accel_vif_state.vif_kref);
-               spin_unlock_irqrestore
-                       (&np->accelerator->vif_states_lock, flags);
-               /* Last chance to get statistics from the accelerator */
-               vif_state->hooks->get_stats(np->netdev, &np->stats);
-               rc = np->accel_vif_state.hooks->remove(dev);
-               
-               kref_put(&np->accel_vif_state.vif_kref,
-                        vif_kref_release);
-               
-               spin_lock_irqsave(&np->accelerator->vif_states_lock,
-                                 flags);
+       if (np->accel_vif_state.hooks) {
+               hooks = np->accel_vif_state.hooks;
 
-               /* 
-                * Try and do the opposite of accelerator_probe_new_vif
-                * to ensure there's no state pointing back at the 
-                * netdev 
-                */
+               /* 
+                * Try and do the opposite of accelerator_probe_new_vif
+                * to ensure there's no state pointing back at the 
+                * netdev 
+                */
                accelerator_remove_single_hook(accelerator, 
-                                              &np->accel_vif_state);
-                               
+                                              &np->accel_vif_state);
+
+               spin_unlock_irqrestore(&accelerator->vif_states_lock, 
+                                      lock_flags);
+
                /* 
-                * Remove the reference taken when the vif_state hooks
-                * were set, must be called without lock held
-                */
-               spin_unlock_irqrestore(&accelerator->vif_states_lock,
-                                      flags);
-               kref_put(&np->accel_vif_state.vif_kref,
-                        vif_kref_release);
+                * No need to do kref_get before calling these hooks as we
+                * can borrow the one we have to drop after this call 
+                */ 
+
+               /* Last chance to get statistics from the accelerator */
+               hooks->get_stats(np->netdev, &np->stats);
+
+               rc = hooks->remove(dev);
+               
+               /* 
+                * Remove the reference taken when the vif_state hooks
+                * were set, must be called without lock held
+                */
+               kref_put(&np->accel_vif_state.vif_kref, vif_kref_release);
        } else {
-               spin_unlock_irqrestore(&np->accelerator->vif_states_lock,
-                                      flags); 
+               spin_unlock_irqrestore(&accelerator->vif_states_lock, 
+                                      lock_flags);     
        }
 
-       return rc;
+       return rc;
 }
-
-
-int netfront_accelerator_call_suspend(struct netfront_info *np,
-                                     struct xenbus_device *dev)
+  
+int netfront_accelerator_call_remove(struct netfront_info *np,
+                                    struct xenbus_device *dev)
 {
-       struct netfront_accel_hooks *hooks;
-       unsigned flags;
-       int rc = 0;
-
-       IPRINTK("netfront_accelerator_call_suspend\n");
+       struct netfront_accel_vif_state *tmp_vif_state;
+       unsigned flags;
 
-       /* 
-        *  Call the suspend accelerator hook.  The use count for the
-        *  accelerator's hooks is incremented for the duration of
-        *  the call to prevent the accelerator being able to modify
-        *  the hooks in the middle (by, for example, unloading)
-        */
-       if (np->accel_vif_state.hooks) {
-               spin_lock_irqsave(&np->accelerator->vif_states_lock, flags); 
-               hooks = np->accel_vif_state.hooks;
-               if (hooks) {
-                       kref_get(&np->accel_vif_state.vif_kref);
-                       spin_unlock_irqrestore
-                               (&np->accelerator->vif_states_lock, flags);
+       /* Check that we've got a device that was accelerated */
+       if (np->accelerator == NULL)
+               return 0;
 
-                       /* Last chance to get stats from the accelerator */
-                       np->accel_vif_state.hooks->get_stats(dev, &np->stats);
-
-                       rc = np->accel_vif_state.hooks->suspend(dev);
+       spin_lock_irqsave(&np->accelerator->vif_states_lock, flags); 
 
-                       kref_put(&np->accel_vif_state.vif_kref,
-                                vif_kref_release);
-               } else {
-                       spin_unlock_irqrestore
-                               (&np->accelerator->vif_states_lock, flags);
+       list_for_each_entry(tmp_vif_state, &np->accelerator->vif_states,
+                           link) {
+               if (tmp_vif_state == &np->accel_vif_state) {
+                       list_del(&np->accel_vif_state.link);
+                       break;
                }
        }
-       return rc;
-}
-
 
-int netfront_accelerator_call_suspend_cancel(struct netfront_info *np,
-                                            struct xenbus_device *dev)
+       /* do_remove drops the lock for us */
+       return do_remove(np, dev, flags, 1);
+}
+  
+  
+int netfront_accelerator_suspend(struct netfront_info *np,
+                                struct xenbus_device *dev)
 {
-       struct netfront_accel_hooks *hooks;
        unsigned flags;
-       int rc = 0;
 
-       IPRINTK(" netfront_accelerator_call_suspend_cancel\n");
+
+       /* Check that we've got a device that was accelerated */
+       if (np->accelerator == NULL)
+               return 0;
 
        /* 
-        *  Call the suspend_cancel accelerator hook.  The use count
-        *  for the accelerator's hooks is incremented for the
-        *  duration of the call to prevent the accelerator being able
-        *  to modify the hooks in the middle (by, for example,
-        *  unloading)
+        * Call the remove accelerator hook, but leave the vif_state
+        * on the accelerator's list in case there is a suspend_cancel.
         */
-       if (np->accel_vif_state.hooks) {
-               spin_lock_irqsave(&np->accelerator->vif_states_lock, flags); 
-               hooks = np->accel_vif_state.hooks;
-               if (hooks) {
-                       kref_get(&np->accel_vif_state.vif_kref);
-                       spin_unlock_irqrestore
-                               (&np->accelerator->vif_states_lock, flags);
-
-                       rc = np->accel_vif_state.hooks->suspend_cancel(dev);
-
-                       kref_put(&np->accel_vif_state.vif_kref,
-                                vif_kref_release);
-               } else {
-                       spin_unlock_irqrestore
-                               (&np->accelerator->vif_states_lock, flags);
-               }
-       }
-       return rc;
+       spin_lock_irqsave(&np->accelerator->vif_states_lock,
+                         flags); 
+       
+       /* do_remove drops the lock for us */
+       return do_remove(np, dev, flags, 0);
 }
-
-
-int netfront_accelerator_call_resume(struct netfront_info *np,
-                                    struct xenbus_device *dev)
+  
+  
+int netfront_accelerator_suspend_cancel(struct netfront_info *np,
+                                       struct xenbus_device *dev)
 {
-       struct netfront_accel_hooks *hooks;
-       unsigned flags;
-       int rc = 0;
-
-       /* 
-        *  Call the resume accelerator hook.  The use count for the
-        *  accelerator's hooks is incremented for the duration of
-        *  the call to prevent the accelerator being able to modify
-        *  the hooks in the middle (by, for example, unloading)
-        */
-       if (np->accel_vif_state.hooks) {
-               spin_lock_irqsave(&np->accelerator->vif_states_lock, flags); 
-               hooks = np->accel_vif_state.hooks;
-               if (hooks) {
-                       kref_get(&np->accel_vif_state.vif_kref);
-                       spin_unlock_irqrestore
-                               (&np->accelerator->vif_states_lock, flags);
-
-                       rc = np->accel_vif_state.hooks->resume(dev);
-
-                       kref_put(&np->accel_vif_state.vif_kref,
-                                vif_kref_release);
-               } else {
-                       spin_unlock_irqrestore
-                               (&np->accelerator->vif_states_lock, flags);
-               }
-       }
-       return rc;
+       struct netfront_accel_vif_state *accel_vif_state = NULL;
+       unsigned flags1, flags2;
+       /* Check that we've got a device that was accelerated */
+       if (np->accelerator == NULL)
+               return 0;
+
+       spin_lock_irqsave(&np->accelerator->vif_states_lock, flags); 
+       /* Find the vif_state from the accelerator's list */
+       list_for_each_entry(accel_vif_state, &np->accelerator->vif_states,
+                           link) {
+               if (accel_vif_state->dev == dev) {
+                       BUG_ON(accel_vif_state != &np->accel_vif_state);
+                       
+                       spin_unlock_irqrestore(&np->accelerator->vif_states_lock,
+                                              flags); 
+                       /*
+                        * Kick things off again to restore
+                        * acceleration as it was before suspend 
+                        */
+                       accelerator_probe_new_vif(np, dev, np->accelerator);
+                       return 0;
+               }
+       }
+       
+       spin_unlock_irqrestore(&np->accelerator->vif_states_lock, flags); 
+       return 0;
+}
+void netfront_accelerator_resume(struct netfront_info *np,
+                                struct xenbus_device *dev)
+{
+       struct netfront_accel_vif_state *accel_vif_state = NULL;
+       spinlock_t *vif_states_lock;
+       unsigned flags;
+       /* Check that we've got a device that was accelerated */
+       if(np->accelerator == NULL)
+               return;
+       spin_lock_irqsave(&np->accelerator->vif_states_lock, flags); 
+       /* Find the vif_state from the accelerator's list */
+       list_for_each_entry(accel_vif_state, &np->accelerator->vif_states, 
+                           link) {
+               if (accel_vif_state->dev == dev) {
+                       BUG_ON(accel_vif_state != &np->accel_vif_state);
+                       /* 
+                        * Remove it from the accelerator's list so
+                        * state is consistent for probing new vifs
+                        * when they get connected
+                        */
+                       list_del(&accel_vif_state->link);
+                       vif_states_lock = &np->accelerator->vif_states_lock;
+                       np->accelerator = NULL;
+                       spin_unlock_irqrestore(vif_states_lock, flags); 
+                       
+                       return;
+               }
+       }
+       spin_unlock_irqrestore(&np->accelerator->vif_states_lock, flags); 
 }
 
 
@@ -852,9 +850,12 @@ void netfront_accelerator_call_backend_changed(struct netfront_info *np,
 void netfront_accelerator_call_stop_napi_irq(struct netfront_info *np,
                                             struct net_device *dev)
 {
+       struct netfront_accelerator *accelerator;
        struct netfront_accel_hooks *hooks;
        unsigned flags;
 
+       accelerator = np->accelerator;
+
        /* 
         * Call the stop_napi_interrupts accelerator hook.  The use
         * count for the accelerator's hooks is incremented for the
@@ -863,13 +864,13 @@ void netfront_accelerator_call_stop_napi_irq(struct netfront_info *np,
         * unloading)
         */
 
-       if (np->accel_vif_state.hooks) {
-               spin_lock_irqsave(&np->accelerator->vif_states_lock, flags); 
+       if (np->accel_vif_state.hooks && accelerator != NULL) {
+               spin_lock_irqsave(&accelerator->vif_states_lock, flags); 
                hooks = np->accel_vif_state.hooks;
-               if (hooks) {
+               if (hooks && np->accelerator == accelerator) {
                        kref_get(&np->accel_vif_state.vif_kref);
                        spin_unlock_irqrestore
-                               (&np->accelerator->vif_states_lock, flags);
+                               (&accelerator->vif_states_lock, flags);
 
                        np->accel_vif_state.hooks->stop_napi_irq(dev);
                
@@ -877,7 +878,7 @@ void netfront_accelerator_call_stop_napi_irq(struct netfront_info *np,
                                 vif_kref_release);
                } else {
                        spin_unlock_irqrestore
-                               (&np->accelerator->vif_states_lock, flags);
+                               (&accelerator->vif_states_lock, flags);
                }
        }
 }
@@ -886,10 +887,13 @@ void netfront_accelerator_call_stop_napi_irq(struct netfront_info *np,
 int netfront_accelerator_call_get_stats(struct netfront_info *np,
                                        struct net_device *dev)
 {
+       struct netfront_accelerator *accelerator;
        struct netfront_accel_hooks *hooks;
        unsigned flags;
        int rc = 0;
 
+       accelerator = np->accelerator;
+
        /* 
         * Call the get_stats accelerator hook.  The use count for the
         * accelerator's hooks is incremented for the duration of the
@@ -897,13 +901,13 @@ int netfront_accelerator_call_get_stats(struct netfront_info *np,
         * hooks in the middle (by, for example, unloading)
         */
 
-       if (np->accel_vif_state.hooks) {
-               spin_lock_irqsave(&np->accelerator->vif_states_lock, flags); 
+       if (np->accel_vif_state.hooks && accelerator != NULL) {
+               spin_lock_irqsave(accelerator->vif_states_lock, flags); 
                hooks = np->accel_vif_state.hooks;
-               if (hooks) {
+               if (hooks && np->accelerator == accelerator) {
                        kref_get(&np->accel_vif_state.vif_kref);
                        spin_unlock_irqrestore
-                               (&np->accelerator->vif_states_lock, flags);
+                               (&accelerator->vif_states_lock, flags);
 
                        rc = np->accel_vif_state.hooks->get_stats(dev,
                                                                  &np->stats);
@@ -912,7 +916,7 @@ int netfront_accelerator_call_get_stats(struct netfront_info *np,
                                 vif_kref_release);
                } else {
                        spin_unlock_irqrestore
-                               (&np->accelerator->vif_states_lock, flags);
+                               (&accelerator->vif_states_lock, flags);
                }
        }
        return rc;
@@ -939,7 +943,7 @@ static void accel_kref_release(struct kref *ref)
        if (accelerator->need_probe) {
                hooks = accelerator->need_probe;
                accelerator->need_probe = NULL;
-               accelerator_probe_vifs(accelerator, hooks, flags);
+               accelerator_probe_vifs(accelerator, hooks, &flags);
        } 
        else
                accelerator->ready_for_probe = 1;
index e5666b6bf18f750e6547b0ed11edcf8ba8d87ce4..ba3b72f41cccaefc0f32e2282eac9fa560017ad2 100644 (file)
@@ -308,14 +308,14 @@ static int __devexit netfront_remove(struct xenbus_device *dev)
 static int netfront_suspend(struct xenbus_device *dev)
 {
        struct netfront_info *info = dev->dev.driver_data;
-       return netfront_accelerator_call_suspend(info, dev);
+       return netfront_accelerator_suspend(info, dev);
 }
 
 
 static int netfront_suspend_cancel(struct xenbus_device *dev)
 {
        struct netfront_info *info = dev->dev.driver_data;
-       return netfront_accelerator_call_suspend_cancel(info, dev);
+       return netfront_accelerator_suspend_cancel(info, dev);
 }
 
 
@@ -331,7 +331,7 @@ static int netfront_resume(struct xenbus_device *dev)
 
        DPRINTK("%s\n", dev->nodename);
 
-       netfront_accelerator_call_resume(info, dev);
+       netfront_accelerator_resume(info, dev);
 
        netif_disconnect_backend(info);
        return 0;
@@ -1507,7 +1507,7 @@ err:
                         *  fast path is likewise
                         */
                        accel_more_to_do = 
-                               np->accel_vif_state.hooks->start_napi_irq(dev);
+                               np->accel_vif_state.hooks->start_napi_irq(dev);
                }
 
                if (!more_to_do && !accel_more_to_do)
index 1e3694453a1cbb238a7cc12bba39b2f890f5b28e..780877f752277b605d9d269521e98512ec344a05 100644 (file)
@@ -60,12 +60,8 @@ struct netfront_accel_hooks {
         */
        int (*new_device)(struct net_device *net_dev, struct xenbus_device *dev);
        /*
-        * suspend, suspend_cancel, resume, remove: Equivalent to the
-        * normal xenbus_* callbacks
+        * remove: Opposite of new_device
         */
-       int (*suspend)(struct xenbus_device *dev);
-       int (*suspend_cancel)(struct xenbus_device *dev);
-       int (*resume)(struct xenbus_device *dev);
        int (*remove)(struct xenbus_device *dev);
        /* 
         * backend_changed: Callback from watch based on backend's
@@ -256,11 +252,8 @@ extern void netfront_accelerator_ready(const char *frontend,
  *
  * frontend: the string describing the accelerator.  Must match the
  * one passed to netfront_accelerator_loaded()
- *
- * wait: 1 => wait for all users of module to complete before
- * returning, thus making it safe to unload on return
  */ 
-extern void netfront_accelerator_stop(const char *frontend, int wait);
+extern void netfront_accelerator_stop(const char *frontend);
 
 /* 
  * Called by an accelerator before waking the net device's TX queue to
@@ -285,14 +278,14 @@ extern
 int netfront_accelerator_call_remove(struct netfront_info *np,
                                     struct xenbus_device *dev);
 extern
-int netfront_accelerator_call_suspend(struct netfront_info *np,
-                                     struct xenbus_device *dev);
+int netfront_accelerator_suspend(struct netfront_info *np,
+                                struct xenbus_device *dev);
 extern
-int netfront_accelerator_call_suspend_cancel(struct netfront_info *np,
-                                            struct xenbus_device *dev);
+int netfront_accelerator_suspend_cancel(struct netfront_info *np,
+                                       struct xenbus_device *dev);
 extern
-int netfront_accelerator_call_resume(struct netfront_info *np,
-                                    struct xenbus_device *dev);
+void netfront_accelerator_resume(struct netfront_info *np,
+                                struct xenbus_device *dev);
 extern
 void netfront_accelerator_call_backend_changed(struct netfront_info *np,
                                               struct xenbus_device *dev,