ia64/linux-2.6.18-xen.hg

changeset 115:1def4dc6afbc

Backend net driver acceleration.
Signed-off-by: Kieran Mansley <kmansley@solarflare.com>
author kfraser@localhost.localdomain
date Mon Jul 09 18:15:12 2007 +0100 (2007-07-09)
parents 729fa35e1e3b
children d9af7736dee4
files drivers/xen/netback/Makefile drivers/xen/netback/accel.c drivers/xen/netback/common.h drivers/xen/netback/netback.c drivers/xen/netback/xenbus.c
line diff
     1.1 --- a/drivers/xen/netback/Makefile	Mon Jul 09 18:09:51 2007 +0100
     1.2 +++ b/drivers/xen/netback/Makefile	Mon Jul 09 18:15:12 2007 +0100
     1.3 @@ -1,5 +1,5 @@
     1.4  obj-$(CONFIG_XEN_NETDEV_BACKEND) := netbk.o
     1.5  obj-$(CONFIG_XEN_NETDEV_LOOPBACK) += netloop.o
     1.6  
     1.7 -netbk-y   := netback.o xenbus.o interface.o
     1.8 +netbk-y   := netback.o xenbus.o interface.o accel.o
     1.9  netloop-y := loopback.o
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/drivers/xen/netback/accel.c	Mon Jul 09 18:15:12 2007 +0100
     2.3 @@ -0,0 +1,207 @@
     2.4 +/******************************************************************************
     2.5 + * drivers/xen/netback/accel.c
     2.6 + *
     2.7 + * Interface between backend virtual network device and accelerated plugin. 
     2.8 + * 
     2.9 + * Copyright (C) 2007 Solarflare Communications, Inc
    2.10 + * 
    2.11 + * This program is free software; you can redistribute it and/or
    2.12 + * modify it under the terms of the GNU General Public License version 2
    2.13 + * as published by the Free Software Foundation; or, when distributed
    2.14 + * separately from the Linux kernel or incorporated into other
    2.15 + * software packages, subject to the following license:
    2.16 + * 
    2.17 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    2.18 + * of this source file (the "Software"), to deal in the Software without
    2.19 + * restriction, including without limitation the rights to use, copy, modify,
    2.20 + * merge, publish, distribute, sublicense, and/or sell copies of the Software,
    2.21 + * and to permit persons to whom the Software is furnished to do so, subject to
    2.22 + * the following conditions:
    2.23 + * 
    2.24 + * The above copyright notice and this permission notice shall be included in
    2.25 + * all copies or substantial portions of the Software.
    2.26 + * 
    2.27 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    2.28 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    2.29 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    2.30 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    2.31 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    2.32 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    2.33 + * IN THE SOFTWARE.
    2.34 + */
    2.35 +
    2.36 +#include <linux/list.h>
    2.37 +#include <asm/atomic.h>
    2.38 +#include <xen/xenbus.h>
    2.39 +
    2.40 +#include "common.h"
    2.41 +
    2.42 +#if 0
    2.43 +#undef DPRINTK
    2.44 +#define DPRINTK(fmt, args...)						\
    2.45 +	printk("netback/accel (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
    2.46 +#endif
    2.47 +
    2.48 +/* 
    2.49 + * A list of available netback accelerator plugin modules (each list
    2.50 + * entry is of type struct netback_accelerator) 
    2.51 + */ 
    2.52 +static struct list_head accelerators_list;
    2.53 +/* Lock used to protect access to accelerators_list */
    2.54 +static spinlock_t accelerators_lock;
    2.55 +
    2.56 +/* 
    2.57 + * Compare a backend to an accelerator, and decide if they are
    2.58 + * compatible (i.e. if the accelerator should be used by the
    2.59 + * backend) 
    2.60 + */
    2.61 +static int match_accelerator(struct backend_info *be, 
    2.62 +			     struct netback_accelerator *accelerator)
    2.63 +{
    2.64 +	/*
    2.65 +	 * This could do with being more sophisticated.  For example,
    2.66 +	 * determine which hardware is being used by each backend from
    2.67 +	 * the bridge and network topology of the domain
    2.68 +	 */
    2.69 +	return be->accelerator == NULL;
    2.70 +}
    2.71 +
    2.72 +/*
    2.73 + * Notify all suitable backends that a new accelerator is available
    2.74 + * and connected.  This will also notify the accelerator plugin module
    2.75 + * that it is being used for a device through the probe hook.
    2.76 + */
    2.77 +static int netback_accelerator_tell_backend(struct device *dev, void *arg)
    2.78 +{
    2.79 +	struct netback_accelerator *accelerator = 
    2.80 +		(struct netback_accelerator *)arg;
    2.81 +	struct xenbus_device *xendev = to_xenbus_device(dev);
    2.82 +
    2.83 +	if (!strcmp("vif", xendev->devicetype)) {
    2.84 +		struct backend_info *be = xendev->dev.driver_data;
    2.85 +
    2.86 +		if (match_accelerator(be, accelerator)) {
    2.87 +			be->accelerator = accelerator;
    2.88 +			atomic_inc(&be->accelerator->use_count);
    2.89 +			be->accelerator->hooks->probe(xendev);
    2.90 +		}
    2.91 +	}
    2.92 +	return 0;
    2.93 +}
    2.94 +
    2.95 +
    2.96 +/*
    2.97 + * Entry point for an netback accelerator plugin module.  Called to
    2.98 + * advertise its presence, and connect to any suitable backends.
    2.99 + */
   2.100 +void netback_connect_accelerator(int id, const char *frontend, 
   2.101 +				 struct netback_accel_hooks *hooks)
   2.102 +{
   2.103 +	struct netback_accelerator *new_accelerator = 
   2.104 +		kmalloc(sizeof(struct netback_accelerator), GFP_KERNEL);
   2.105 +	unsigned frontend_len, flags;
   2.106 +
   2.107 +	if (!new_accelerator) {
   2.108 +		DPRINTK("%s: failed to allocate memory for accelerator\n",
   2.109 +			__FUNCTION__);
   2.110 +		return;
   2.111 +	}
   2.112 +
   2.113 +	new_accelerator->id = id;
   2.114 +	
   2.115 +	frontend_len = strlen(frontend)+1;
   2.116 +	new_accelerator->frontend = kmalloc(frontend_len, GFP_KERNEL);
   2.117 +	if (!new_accelerator->frontend) {
   2.118 +		DPRINTK("%s: failed to allocate memory for frontend string\n",
   2.119 +			__FUNCTION__);
   2.120 +		kfree(new_accelerator);
   2.121 +		return;
   2.122 +	}
   2.123 +	strlcpy(new_accelerator->frontend, frontend, frontend_len);
   2.124 +	
   2.125 +	new_accelerator->hooks = hooks;
   2.126 +
   2.127 +	atomic_set(&new_accelerator->use_count, 0);
   2.128 +	
   2.129 +	spin_lock_irqsave(&accelerators_lock, flags);
   2.130 +	list_add(&new_accelerator->link, &accelerators_list);
   2.131 +	spin_unlock_irqrestore(&accelerators_lock, flags);
   2.132 +	
   2.133 +	/* tell existing backends about new plugin */
   2.134 +	xenbus_for_each_backend(new_accelerator, 
   2.135 +				netback_accelerator_tell_backend);
   2.136 +
   2.137 +}
   2.138 +EXPORT_SYMBOL_GPL(netback_connect_accelerator);
   2.139 +
   2.140 +
   2.141 +/* 
   2.142 + * Disconnect an accerator plugin module that has previously been
   2.143 + * connected.
   2.144 + *
   2.145 + * This should only be allowed when there are no remaining users -
   2.146 + * i.e. it is not necessary to go through and clear all the hooks, as
   2.147 + * they should have already been removed.  This is enforced through a
   2.148 + * usage count and BUG_ON(use!=0), but should be made more user-friendly
   2.149 + */
   2.150 +void netback_disconnect_accelerator(int id, const char *frontend)
   2.151 +{
   2.152 +	struct netback_accelerator *accelerator, *next;
   2.153 +	unsigned flags;
   2.154 +
   2.155 +	spin_lock_irqsave(&accelerators_lock, flags);
   2.156 +	list_for_each_entry_safe(accelerator, next, &accelerators_list, link) {
   2.157 +		if (strcmp(frontend, accelerator->frontend)) {
   2.158 +			BUG_ON(atomic_read(&accelerator->use_count) != 0);
   2.159 +			list_del(&accelerator->link);
   2.160 +			spin_unlock_irqrestore(&accelerators_lock, flags);
   2.161 +			kfree(accelerator->frontend);
   2.162 +			kfree(accelerator);
   2.163 +			return;
   2.164 +		}
   2.165 +	}
   2.166 +	spin_unlock_irqrestore(&accelerators_lock, flags);
   2.167 +}
   2.168 +EXPORT_SYMBOL_GPL(netback_disconnect_accelerator);
   2.169 +
   2.170 +
   2.171 +void netback_probe_accelerators(struct backend_info *be,
   2.172 +				struct xenbus_device *dev)
   2.173 +{
   2.174 +	struct netback_accelerator *accelerator;
   2.175 +	unsigned flags;
   2.176 +
   2.177 +	/* 
   2.178 +	 * Check list of accelerators to see if any is suitable, and
   2.179 +	 * use it if it is.
   2.180 +	 */
   2.181 +	spin_lock_irqsave(&accelerators_lock, flags);
   2.182 +	list_for_each_entry(accelerator, &accelerators_list, link) { 
   2.183 +		if (match_accelerator(be, accelerator)) {
   2.184 +			be->accelerator = accelerator;
   2.185 +			atomic_inc(&be->accelerator->use_count);
   2.186 +			be->accelerator->hooks->probe(dev);
   2.187 +			break;
   2.188 +		}
   2.189 +	}
   2.190 +	spin_unlock_irqrestore(&accelerators_lock, flags);
   2.191 +}
   2.192 +
   2.193 +
   2.194 +void netback_remove_accelerators(struct backend_info *be,
   2.195 +				 struct xenbus_device *dev)
   2.196 +{
   2.197 +	/* Notify the accelerator (if any) of this device's removal */
   2.198 +	if ( be->accelerator ) {
   2.199 +		be->accelerator->hooks->remove(dev);
   2.200 +		atomic_dec(&be->accelerator->use_count);
   2.201 +	}
   2.202 +	be->accelerator = NULL;
   2.203 +}
   2.204 +
   2.205 +
   2.206 +void netif_accel_init(void)
   2.207 +{
   2.208 +	INIT_LIST_HEAD(&accelerators_list);
   2.209 +	spin_lock_init(&accelerators_lock);
   2.210 +}
     3.1 --- a/drivers/xen/netback/common.h	Mon Jul 09 18:09:51 2007 +0100
     3.2 +++ b/drivers/xen/netback/common.h	Mon Jul 09 18:15:12 2007 +0100
     3.3 @@ -45,6 +45,7 @@
     3.4  #include <xen/interface/grant_table.h>
     3.5  #include <xen/gnttab.h>
     3.6  #include <xen/driver_util.h>
     3.7 +#include <xen/xenbus.h>
     3.8  
     3.9  #define DPRINTK(_f, _a...)			\
    3.10  	pr_debug("(file=%s, line=%d) " _f,	\
    3.11 @@ -122,6 +123,49 @@ enum {
    3.12  
    3.13  extern int netbk_copy_skb_mode;
    3.14  
    3.15 +/* Function pointers into netback accelerator plugin modules */
    3.16 +struct netback_accel_hooks {
    3.17 +	int  (*probe)(struct xenbus_device *dev);
    3.18 +	int (*remove)(struct xenbus_device *dev);
    3.19 +};
    3.20 +
    3.21 +/* Structure to track the state of a netback accelerator plugin */
    3.22 +struct netback_accelerator {
    3.23 +	struct list_head link;
    3.24 +	int id;
    3.25 +	char *frontend;
    3.26 +	atomic_t use_count;
    3.27 +	struct netback_accel_hooks *hooks;
    3.28 +};
    3.29 +
    3.30 +struct backend_info {
    3.31 +	struct xenbus_device *dev;
    3.32 +	netif_t *netif;
    3.33 +	enum xenbus_state frontend_state;
    3.34 +
    3.35 +	/* State relating to the netback accelerator */
    3.36 +	void *netback_accel_priv;
    3.37 +	/* The accelerator that this backend is currently using */
    3.38 +	struct netback_accelerator *accelerator;
    3.39 +};
    3.40 +
    3.41 +/* Connect an accelerator plugin module to netback */
    3.42 +extern void netback_connect_accelerator(int id, const char *frontend, 
    3.43 +					struct netback_accel_hooks *hooks);
    3.44 +/* Disconnect a previously connected accelerator pluging module */
    3.45 +extern void netback_disconnect_accelerator(int id, const char *frontend);
    3.46 +
    3.47 +
    3.48 +extern
    3.49 +void netback_probe_accelerators(struct backend_info *be,
    3.50 +				struct xenbus_device *dev);
    3.51 +extern
    3.52 +void netback_remove_accelerators(struct backend_info *be,
    3.53 +				 struct xenbus_device *dev);
    3.54 +extern
    3.55 +void netif_accel_init(void);
    3.56 +
    3.57 +
    3.58  #define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE)
    3.59  #define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE)
    3.60  
     4.1 --- a/drivers/xen/netback/netback.c	Mon Jul 09 18:09:51 2007 +0100
     4.2 +++ b/drivers/xen/netback/netback.c	Mon Jul 09 18:15:12 2007 +0100
     4.3 @@ -1587,6 +1587,8 @@ static int __init netback_init(void)
     4.4  			netbk_copy_skb_mode = NETBK_DELAYED_COPY_SKB;
     4.5  	}
     4.6  
     4.7 +	netif_accel_init();
     4.8 +
     4.9  	netif_xenbus_init();
    4.10  
    4.11  #ifdef NETBE_DEBUG_INTERRUPT
     5.1 --- a/drivers/xen/netback/xenbus.c	Mon Jul 09 18:09:51 2007 +0100
     5.2 +++ b/drivers/xen/netback/xenbus.c	Mon Jul 09 18:15:12 2007 +0100
     5.3 @@ -28,11 +28,6 @@
     5.4      printk("netback/xenbus (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
     5.5  #endif
     5.6  
     5.7 -struct backend_info {
     5.8 -	struct xenbus_device *dev;
     5.9 -	netif_t *netif;
    5.10 -	enum xenbus_state frontend_state;
    5.11 -};
    5.12  
    5.13  static int connect_rings(struct backend_info *);
    5.14  static void connect(struct backend_info *);
    5.15 @@ -42,6 +37,8 @@ static int netback_remove(struct xenbus_
    5.16  {
    5.17  	struct backend_info *be = dev->dev.driver_data;
    5.18  
    5.19 +	netback_remove_accelerators(be, dev);
    5.20 +
    5.21  	if (be->netif) {
    5.22  		netif_disconnect(be->netif);
    5.23  		be->netif = NULL;
    5.24 @@ -125,6 +122,8 @@ static int netback_probe(struct xenbus_d
    5.25  		goto fail;
    5.26  	}
    5.27  
    5.28 +	netback_probe_accelerators(be, dev);
    5.29 +
    5.30  	err = xenbus_switch_state(dev, XenbusStateInitWait);
    5.31  	if (err)
    5.32  		goto fail;