]> xenbits.xensource.com Git - legacy/linux-2.6.18-xen.git/commitdiff
netfront accel: Get network stats from accelerator plugin
authorKeir Fraser <keir@xensource.com>
Tue, 30 Oct 2007 17:29:55 +0000 (17:29 +0000)
committerKeir Fraser <keir@xensource.com>
Tue, 30 Oct 2007 17:29:55 +0000 (17:29 +0000)
Signed-off-by <kmansley@solarflare.com>

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

index bb45143aa1194b0366a10582b3151ce748c9af92..cfe3a18ed161cb8e30cd9cfa09fa8b1c4f5e2123 100644 (file)
@@ -529,6 +529,7 @@ accelerator_remove_single_hook(struct netfront_accelerator *accelerator,
 static void accelerator_remove_hooks(struct netfront_accelerator *accelerator,
                                     int remove_master)
 {
+       struct netfront_accel_hooks *hooks;
        struct netfront_accel_vif_state *vif_state, *tmp;
        unsigned flags;
 
@@ -537,6 +538,7 @@ static void accelerator_remove_hooks(struct netfront_accelerator *accelerator,
        list_for_each_entry_safe(vif_state, tmp,
                                 &accelerator->vif_states,
                                 link) {
+               hooks = vif_state->hooks;
                accelerator_remove_single_hook(accelerator, vif_state);
 
                /* 
@@ -544,7 +546,12 @@ static void accelerator_remove_hooks(struct netfront_accelerator *accelerator,
                 * were set, 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);
+
                kref_put(&vif_state->vif_kref, vif_kref_release);
+
                spin_lock_irqsave(&accelerator->vif_states_lock, flags);
        }
        
@@ -663,7 +670,8 @@ int netfront_accelerator_call_remove(struct netfront_info *np,
                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,
@@ -720,6 +728,9 @@ int netfront_accelerator_call_suspend(struct netfront_info *np,
                        spin_unlock_irqrestore
                                (&np->accelerator->vif_states_lock, flags);
 
+                       /* 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);
 
                        kref_put(&np->accel_vif_state.vif_kref,
@@ -872,6 +883,42 @@ 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_accel_hooks *hooks;
+       unsigned flags;
+       int rc = 0;
+
+       /* 
+        * Call the get_stats 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->get_stats(dev,
+                                                                 &np->stats);
+               
+                       kref_put(&np->accel_vif_state.vif_kref,
+                                vif_kref_release);
+               } else {
+                       spin_unlock_irqrestore
+                               (&np->accelerator->vif_states_lock, flags);
+               }
+       }
+       return rc;
+}
+
+
 /* 
  * Once all users of hooks have kref_put()'d we can signal that it's
  * safe to unload
index 9ec7eeb33b9cd75c1e4569f1b4065b0d5cfaff51..e5666b6bf18f750e6547b0ed11edcf8ba8d87ce4 100644 (file)
@@ -1674,6 +1674,8 @@ static int network_close(struct net_device *dev)
 static struct net_device_stats *network_get_stats(struct net_device *dev)
 {
        struct netfront_info *np = netdev_priv(dev);
+
+       netfront_accelerator_call_get_stats(np, dev);
        return &np->stats;
 }
 
index 6be409392a17f458c1d54d68b75070f13cbc35af..1e3694453a1cbb238a7cc12bba39b2f890f5b28e 100644 (file)
@@ -96,12 +96,17 @@ struct netfront_accel_hooks {
         * path has slots too
         */
        int (*check_busy)(struct net_device *dev);
+       /*
+        * Get the fastpath network statistics
+        */
+       int (*get_stats)(struct net_device *dev,
+                        struct net_device_stats *stats);
 };
 
 
 /* Version of API/protocol for communication between netfront and
    acceleration plugin supported */
-#define NETFRONT_ACCEL_VERSION 0x00010000
+#define NETFRONT_ACCEL_VERSION 0x00010001
 
 /* 
  * Per-netfront device state for the accelerator.  This is used to
@@ -295,7 +300,9 @@ void netfront_accelerator_call_backend_changed(struct netfront_info *np,
 extern
 void netfront_accelerator_call_stop_napi_irq(struct netfront_info *np,
                                             struct net_device *dev);
-
+extern
+int netfront_accelerator_call_get_stats(struct netfront_info *np,
+                                       struct net_device *dev);
 extern
 int netfront_load_accelerator(struct netfront_info *np, 
                              struct xenbus_device *dev,