# HG changeset patch
# User cl349@xxxxxxxxxxxxxxxxxxxx
# Node ID b402e77aac4674f938591dd718fb1259bb9e2100
# Parent d4ce28d819a8297ba3c82f3053c24ee125476dd5
Switch network setup over to xenbus.
Signed-off-by: Christian Limpach <Christian.Limpach@xxxxxxxxxxxx>
diff -r d4ce28d819a8 -r b402e77aac46
linux-2.6-xen-sparse/arch/xen/kernel/reboot.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Wed Aug 24 22:21:24 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Wed Aug 24 22:22:11 2005
@@ -128,14 +128,6 @@
/* Hmmm... a cleaner interface to suspend/resume blkdevs would be nice. */
/* XXX SMH: yes it would :-( */
-
-#ifdef CONFIG_XEN_NETDEV_FRONTEND
- extern void netif_suspend(void);
- extern void netif_resume(void);
-#else
-#define netif_suspend() do{}while(0)
-#define netif_resume() do{}while(0)
-#endif
#ifdef CONFIG_XEN_USB_FRONTEND
extern void usbif_resume();
@@ -218,8 +210,6 @@
kmem_cache_shrink(pgd_cache);
#endif
- netif_suspend();
-
time_suspend();
#ifdef CONFIG_SMP
@@ -276,8 +266,6 @@
#endif
time_resume();
-
- netif_resume();
usbif_resume();
diff -r d4ce28d819a8 -r b402e77aac46
linux-2.6-xen-sparse/drivers/xen/console/console.c
--- a/linux-2.6-xen-sparse/drivers/xen/console/console.c Wed Aug 24
22:21:24 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/console/console.c Wed Aug 24
22:22:11 2005
@@ -240,7 +240,11 @@
#endif
/*** Useful function for console debugging -- goes straight to Xen. ***/
+#ifdef CONFIG_XEN_PRIVILEGED_GUEST
asmlinkage int xprintk(const char *fmt, ...)
+#else
+asmlinkage int xprintk(const char *fmt, ...)
+#endif
{
va_list args;
int printk_len;
diff -r d4ce28d819a8 -r b402e77aac46
linux-2.6-xen-sparse/drivers/xen/netback/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/netback/Makefile Wed Aug 24 22:21:24 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/Makefile Wed Aug 24 22:22:11 2005
@@ -1,2 +1,2 @@
-obj-y := netback.o control.o interface.o loopback.o
+obj-y := netback.o xenbus.o interface.o loopback.o
diff -r d4ce28d819a8 -r b402e77aac46
linux-2.6-xen-sparse/drivers/xen/netback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h Wed Aug 24 22:21:24 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h Wed Aug 24 22:22:11 2005
@@ -59,6 +59,7 @@
grant_ref_t rx_shmem_ref;
#endif
unsigned int evtchn;
+ unsigned int remote_evtchn;
/* The shared rings and indexes. */
netif_tx_interface_t *tx;
@@ -93,21 +94,26 @@
struct net_device *dev;
struct net_device_stats stats;
- struct work_struct work;
+ struct work_struct free_work;
} netif_t;
-void netif_create(netif_be_create_t *create);
+int netif_create(netif_t *netif);
void netif_destroy(netif_be_destroy_t *destroy);
void netif_creditlimit(netif_be_creditlimit_t *creditlimit);
-void netif_connect(netif_be_connect_t *connect);
int netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id);
void netif_disconnect_complete(netif_t *netif);
netif_t *netif_find_by_handle(domid_t domid, unsigned int handle);
+
+netif_t *alloc_netif(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN]);
+void free_netif_callback(netif_t *netif);
+int netif_map(netif_t *netif, unsigned long tx_ring_ref,
+ unsigned long rx_ring_ref, unsigned int evtchn);
+
#define netif_get(_b) (atomic_inc(&(_b)->refcnt))
#define netif_put(_b) \
do { \
if ( atomic_dec_and_test(&(_b)->refcnt) ) \
- netif_disconnect_complete(_b); \
+ free_netif_callback(_b); \
} while (0)
void netif_interface_init(void);
diff -r d4ce28d819a8 -r b402e77aac46
linux-2.6-xen-sparse/drivers/xen/netback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Wed Aug 24
22:21:24 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Wed Aug 24
22:22:11 2005
@@ -9,10 +9,6 @@
#include "common.h"
#include <linux/rtnetlink.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
-#endif
-
#define NETIF_HASHSZ 1024
#define NETIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(NETIF_HASHSZ-1))
@@ -66,87 +62,20 @@
return 0;
}
-static void __netif_disconnect_complete(void *arg)
-{
- netif_t *netif = (netif_t *)arg;
- ctrl_msg_t cmsg;
- netif_be_disconnect_t disc;
-#if defined(CONFIG_XEN_NETDEV_GRANT_RX) || defined(CONFIG_XEN_NETDEV_GRANT_TX)
- struct gnttab_unmap_grant_ref op;
-#endif
-
- /*
- * These can't be done in netif_disconnect() because at that point there
- * may be outstanding requests in the network stack whose asynchronous
- * responses must still be notified to the remote driver.
- */
-
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
- op.host_addr = netif->tx_shmem_vaddr;
- op.handle = netif->tx_shmem_handle;
- op.dev_bus_addr = 0;
- BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
-#endif
-
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
- op.host_addr = netif->rx_shmem_vaddr;
- op.handle = netif->rx_shmem_handle;
- op.dev_bus_addr = 0;
- BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
-#endif
-
-
- vfree(netif->tx); /* Frees netif->rx as well. */
-
- /* Construct the deferred response message. */
- cmsg.type = CMSG_NETIF_BE;
- cmsg.subtype = CMSG_NETIF_BE_DISCONNECT;
- cmsg.id = netif->disconnect_rspid;
- cmsg.length = sizeof(netif_be_disconnect_t);
- disc.domid = netif->domid;
- disc.netif_handle = netif->handle;
- disc.status = NETIF_BE_STATUS_OKAY;
- memcpy(cmsg.msg, &disc, sizeof(disc));
-
- /*
- * Make sure message is constructed /before/ status change, because
- * after the status change the 'netif' structure could be deallocated at
- * any time. Also make sure we send the response /after/ status change,
- * as otherwise a subsequent CONNECT request could spuriously fail if
- * another CPU doesn't see the status change yet.
- */
- mb();
- if ( netif->status != DISCONNECTING )
- BUG();
- netif->status = DISCONNECTED;
- mb();
-
- /* Send the successful response. */
- ctrl_if_send_response(&cmsg);
-}
-
-void netif_disconnect_complete(netif_t *netif)
-{
- INIT_WORK(&netif->work, __netif_disconnect_complete, (void *)netif);
- schedule_work(&netif->work);
-}
-
-void netif_create(netif_be_create_t *create)
-{
- int err = 0;
- domid_t domid = create->domid;
- unsigned int handle = create->netif_handle;
+netif_t *alloc_netif(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN])
+{
+ int err = 0, i;
struct net_device *dev;
- netif_t **pnetif, *netif;
- char name[IFNAMSIZ] = {};
+ netif_t **pnetif, *netif;
+ char name[IFNAMSIZ] = {};
snprintf(name, IFNAMSIZ - 1, "vif%u.%u", domid, handle);
dev = alloc_netdev(sizeof(netif_t), name, ether_setup);
if ( dev == NULL )
{
DPRINTK("Could not create netif: out of memory\n");
- create->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
- return;
+ // create->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
+ return NULL;
}
netif = netdev_priv(dev);
@@ -167,9 +96,9 @@
if ( ((*pnetif)->domid == domid) && ((*pnetif)->handle == handle) )
{
DPRINTK("Could not create netif: already exists\n");
- create->status = NETIF_BE_STATUS_INTERFACE_EXISTS;
+ // create->status = NETIF_BE_STATUS_INTERFACE_EXISTS;
free_netdev(dev);
- return;
+ return NULL;
}
pnetif = &(*pnetif)->hash_next;
}
@@ -183,9 +112,10 @@
/* Disable queuing. */
dev->tx_queue_len = 0;
- if ( (create->be_mac[0] == 0) && (create->be_mac[1] == 0) &&
- (create->be_mac[2] == 0) && (create->be_mac[3] == 0) &&
- (create->be_mac[4] == 0) && (create->be_mac[5] == 0) )
+ for (i = 0; i < ETH_ALEN; i++)
+ if (be_mac[i] != 0)
+ break;
+ if (i == ETH_ALEN)
{
/*
* Initialise a dummy MAC address. We choose the numerically largest
@@ -197,10 +127,8 @@
}
else
{
- memcpy(dev->dev_addr, create->be_mac, ETH_ALEN);
- }
-
- memcpy(netif->fe_dev_addr, create->mac, ETH_ALEN);
+ memcpy(dev->dev_addr, be_mac, ETH_ALEN);
+ }
rtnl_lock();
err = register_netdevice(dev);
@@ -210,16 +138,187 @@
{
DPRINTK("Could not register new net device %s: err=%d\n",
dev->name, err);
- create->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
+ // create->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
free_netdev(dev);
- return;
+ return NULL;
}
netif->hash_next = *pnetif;
*pnetif = netif;
DPRINTK("Successfully created netif\n");
- create->status = NETIF_BE_STATUS_OKAY;
+ // create->status = NETIF_BE_STATUS_OKAY;
+ return netif;
+}
+
+static int map_frontend_page(netif_t *netif, unsigned long localaddr,
+ unsigned long tx_ring_ref, unsigned long
rx_ring_ref)
+{
+#if !defined(CONFIG_XEN_NETDEV_GRANT_TX)||!defined(CONFIG_XEN_NETDEV_GRANT_RX)
+ pgprot_t prot = __pgprot(_KERNPG_TABLE);
+ int err;
+#endif
+#if defined(CONFIG_XEN_NETDEV_GRANT_TX)
+ {
+ struct gnttab_map_grant_ref op;
+
+ /* Map: Use the Grant table reference */
+ op.host_addr = localaddr;
+ op.flags = GNTMAP_host_map;
+ op.ref = tx_ring_ref;
+ op.dom = netif->domid;
+
+ BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
+ if (op.handle < 0) {
+ DPRINTK(" Grant table operation failure !\n");
+ return op.handle;
+ }
+
+ netif->tx_shmem_ref = tx_ring_ref;
+ netif->tx_shmem_handle = op.handle;
+ netif->tx_shmem_vaddr = localaddr;
+ }
+#else
+ err = direct_remap_area_pages(&init_mm, localaddr,
+ tx_ring_ref<<PAGE_SHIFT, PAGE_SIZE,
+ prot, netif->domid);
+ if (err)
+ return err;
+#endif
+
+#if defined(CONFIG_XEN_NETDEV_GRANT_RX)
+ {
+ struct gnttab_map_grant_ref op;
+
+ /* Map: Use the Grant table reference */
+ op.host_addr = localaddr + PAGE_SIZE;
+ op.flags = GNTMAP_host_map;
+ op.ref = rx_ring_ref;
+ op.dom = netif->domid;
+
+ BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) );
+ if (op.handle < 0) {
+ DPRINTK(" Grant table operation failure !\n");
+ return op.handle;
+ }
+
+ netif->rx_shmem_ref = rx_ring_ref;
+ netif->rx_shmem_handle = op.handle;
+ netif->rx_shmem_vaddr = localaddr + PAGE_SIZE;
+ }
+#else
+ err = direct_remap_area_pages(&init_mm, localaddr + PAGE_SIZE,
+ rx_ring_ref<<PAGE_SHIFT, PAGE_SIZE,
+ prot, netif->domid);
+ if (err)
+ return err;
+#endif
+
+ return 0;
+}
+
+static void unmap_frontend_page(netif_t *netif)
+{
+#if defined(CONFIG_XEN_NETDEV_GRANT_RX) || defined(CONFIG_XEN_NETDEV_GRANT_TX)
+ struct gnttab_unmap_grant_ref op;
+#endif
+
+#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+ op.host_addr = netif->tx_shmem_vaddr;
+ op.handle = netif->tx_shmem_handle;
+ op.dev_bus_addr = 0;
+ BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
+#endif
+
+#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+ op.host_addr = netif->rx_shmem_vaddr;
+ op.handle = netif->rx_shmem_handle;
+ op.dev_bus_addr = 0;
+ BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
+#endif
+}
+
+int netif_map(netif_t *netif, unsigned long tx_ring_ref,
+ unsigned long rx_ring_ref, unsigned int evtchn)
+{
+ struct vm_struct *vma;
+ evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain };
+ int err;
+
+#if 0
+ if ( netif->status != DISCONNECTED ) {
+ connect->status = NETIF_BE_STATUS_INTERFACE_CONNECTED;
+ return;
+ }
+#endif
+
+ if ( (vma = get_vm_area(2*PAGE_SIZE, VM_IOREMAP)) == NULL ) {
+ // connect->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
+ return -ENOMEM;
+ }
+
+ err = map_frontend_page(netif, (unsigned long)vma->addr, tx_ring_ref,
+ rx_ring_ref);
+ if (err) {
+ vfree(vma->addr);
+ return err;
+ }
+
+ op.u.bind_interdomain.dom1 = DOMID_SELF;
+ op.u.bind_interdomain.dom2 = netif->domid;
+ op.u.bind_interdomain.port1 = 0;
+ op.u.bind_interdomain.port2 = evtchn;
+ err = HYPERVISOR_event_channel_op(&op);
+ if (err) {
+ unmap_frontend_page(netif);
+ vfree(vma->addr);
+ return err;
+ }
+
+ netif->evtchn = op.u.bind_interdomain.port1;
+ netif->remote_evtchn = evtchn;
+
+ netif->tx_shmem_frame = tx_ring_ref;
+ netif->rx_shmem_frame = rx_ring_ref;
+ netif->tx =
+ (netif_tx_interface_t *)vma->addr;
+ netif->rx =
+ (netif_rx_interface_t *)((char *)vma->addr + PAGE_SIZE);
+ netif->tx->resp_prod = netif->rx->resp_prod = 0;
+ netif_get(netif);
+ wmb(); /* Other CPUs see new state before interface is started. */
+
+ rtnl_lock();
+ netif->status = CONNECTED;
+ wmb();
+ if ( netif_running(netif->dev) )
+ __netif_up(netif);
+ rtnl_unlock();
+
+ // connect->status = NETIF_BE_STATUS_OKAY;
+ return 0;
+}
+
+static void free_netif(void *arg)
+{
+ netif_t *netif = (netif_t *)arg;
+
+ /*
+ * These can't be done in netif_disconnect() because at that point there
+ * may be outstanding requests in the network stack whose asynchronous
+ * responses must still be notified to the remote driver.
+ */
+
+ unmap_frontend_page(netif);
+ vfree(netif->tx); /* Frees netif->rx as well. */
+
+ netif->status = DISCONNECTED;
+}
+
+void free_netif_callback(netif_t *netif)
+{
+ INIT_WORK(&netif->free_work, free_netif, (void *)netif);
+ schedule_work(&netif->free_work);
}
void netif_destroy(netif_be_destroy_t *destroy)
@@ -284,147 +383,6 @@
}
creditlimit->status = NETIF_BE_STATUS_OKAY;
-}
-
-void netif_connect(netif_be_connect_t *connect)
-{
- domid_t domid = connect->domid;
- unsigned int handle = connect->netif_handle;
- unsigned int evtchn = connect->evtchn;
- unsigned long tx_shmem_frame = connect->tx_shmem_frame;
- unsigned long rx_shmem_frame = connect->rx_shmem_frame;
- struct vm_struct *vma;
-#if !defined(CONFIG_XEN_NETDEV_GRANT_TX)||!defined(CONFIG_XEN_NETDEV_GRANT_RX)
- pgprot_t prot = __pgprot(_KERNPG_TABLE);
- int error;
-#endif
- netif_t *netif;
-
- netif = netif_find_by_handle(domid, handle);
- if ( unlikely(netif == NULL) ) {
- DPRINTK("netif_connect attempted for non-existent netif (%u,%u)\n",
- connect->domid, connect->netif_handle);
- connect->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND;
- return;
- }
-
- if ( netif->status != DISCONNECTED ) {
- connect->status = NETIF_BE_STATUS_INTERFACE_CONNECTED;
- return;
- }
-
- if ( (vma = get_vm_area(2*PAGE_SIZE, VM_IOREMAP)) == NULL ) {
- connect->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
- return;
- }
-
-
-#if defined(CONFIG_XEN_NETDEV_GRANT_TX)
- {
- struct gnttab_map_grant_ref op;
- int tx_ref = connect->tx_shmem_ref;
-
- /* Map: Use the Grant table reference */
- op.host_addr = VMALLOC_VMADDR(vma->addr);
- op.flags = GNTMAP_host_map;
- op.ref = tx_ref;
- op.dom = domid;
-
- if ((HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) < 0) ||
- (op.handle < 0)) {
- DPRINTK(" Grant table operation failure !\n");
- connect->status = NETIF_BE_STATUS_MAPPING_ERROR;
- vfree(vma->addr);
- return;
- }
-
- netif->tx_shmem_ref = tx_ref;
- netif->tx_shmem_handle = op.handle;
- netif->tx_shmem_vaddr = VMALLOC_VMADDR(vma->addr);
- }
-
-
-#else
- error = direct_remap_area_pages(&init_mm,
- VMALLOC_VMADDR(vma->addr),
- tx_shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
- prot, domid);
- if ( error != 0 )
- {
- if ( error == -ENOMEM )
- connect->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
- else if ( error == -EFAULT )
- connect->status = NETIF_BE_STATUS_MAPPING_ERROR;
- else
- connect->status = NETIF_BE_STATUS_ERROR;
- vfree(vma->addr);
- return;
- }
-#endif
-
-
-#if defined(CONFIG_XEN_NETDEV_GRANT_RX)
- {
- struct gnttab_map_grant_ref op;
- int rx_ref = connect->rx_shmem_ref;
-
-
- /* Map: Use the Grant table reference */
- op.host_addr = VMALLOC_VMADDR(vma->addr) + PAGE_SIZE;
- op.flags = GNTMAP_host_map;
- op.ref = rx_ref;
- op.dom = domid;
-
- if ((HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) < 0) ||
- (op.handle < 0)) {
- DPRINTK(" Grant table operation failure !\n");
- connect->status = NETIF_BE_STATUS_MAPPING_ERROR;
- vfree(vma->addr);
- return;
- }
-
- netif->rx_shmem_ref = rx_ref;
- netif->rx_shmem_handle = handle;
- netif->rx_shmem_vaddr = VMALLOC_VMADDR(vma->addr) + PAGE_SIZE;
- }
-#else
- error = direct_remap_area_pages(&init_mm,
- VMALLOC_VMADDR(vma->addr) + PAGE_SIZE,
- rx_shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
- prot, domid);
- if ( error != 0 )
- {
- if ( error == -ENOMEM )
- connect->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
- else if ( error == -EFAULT )
- connect->status = NETIF_BE_STATUS_MAPPING_ERROR;
- else
- connect->status = NETIF_BE_STATUS_ERROR;
- vfree(vma->addr);
- return;
- }
-
-#endif
-
- netif->evtchn = evtchn;
- netif->tx_shmem_frame = tx_shmem_frame;
- netif->rx_shmem_frame = rx_shmem_frame;
- netif->tx =
- (netif_tx_interface_t *)vma->addr;
- netif->rx =
- (netif_rx_interface_t *)((char *)vma->addr + PAGE_SIZE);
- netif->tx->resp_prod = netif->rx->resp_prod = 0;
- netif_get(netif);
- wmb(); /* Other CPUs see new state before interface is started. */
-
- rtnl_lock();
- netif->status = CONNECTED;
- wmb();
- if ( netif_running(netif->dev) )
- __netif_up(netif);
- rtnl_unlock();
-
- connect->status = NETIF_BE_STATUS_OKAY;
}
int netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id)
diff -r d4ce28d819a8 -r b402e77aac46
linux-2.6-xen-sparse/drivers/xen/netback/netback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Wed Aug 24
22:21:24 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Wed Aug 24
22:22:11 2005
@@ -987,7 +987,7 @@
spin_lock_init(&net_schedule_list_lock);
INIT_LIST_HEAD(&net_schedule_list);
- netif_ctrlif_init();
+ netif_xenbus_init();
(void)request_irq(bind_virq_to_irq(VIRQ_DEBUG),
netif_be_dbg, SA_SHIRQ,
diff -r d4ce28d819a8 -r b402e77aac46
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Wed Aug 24
22:21:24 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Wed Aug 24
22:22:11 2005
@@ -48,7 +48,7 @@
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm-xen/evtchn.h>
-#include <asm-xen/ctrl_if.h>
+#include <asm-xen/xenbus.h>
#include <asm-xen/xen-public/io/netif.h>
#include <asm-xen/balloon.h>
#include <asm/page.h>
@@ -112,7 +112,6 @@
#endif
#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX)
-static domid_t rdomid = 0;
#define GRANT_INVALID_REF (0xFFFF)
#endif
@@ -135,10 +134,11 @@
static struct list_head dev_list;
+#define netfront_info net_private
struct net_private
{
struct list_head list;
- struct net_device *dev;
+ struct net_device *netdev;
struct net_device_stats stats;
NETIF_RING_IDX rx_resp_cons, tx_resp_cons;
@@ -176,6 +176,14 @@
*/
struct sk_buff *tx_skbs[NETIF_TX_RING_SIZE+1];
struct sk_buff *rx_skbs[NETIF_RX_RING_SIZE+1];
+
+ struct xenbus_device *xbdev;
+ char *backend;
+ int backend_id;
+ struct xenbus_watch watch;
+ int tx_ring_ref;
+ int rx_ring_ref;
+ u8 mac[ETH_ALEN];
};
/* Access macros for acquiring freeing slots in {tx,rx}_skbs[]. */
@@ -187,13 +195,6 @@
(_list)[0] = (_list)[_id]; \
(unsigned short)_id; })
-static char *status_name[] = {
- [NETIF_INTERFACE_STATUS_CLOSED] = "closed",
- [NETIF_INTERFACE_STATUS_DISCONNECTED] = "disconnected",
- [NETIF_INTERFACE_STATUS_CONNECTED] = "connected",
- [NETIF_INTERFACE_STATUS_CHANGED] = "changed",
-};
-
static char *be_state_name[] = {
[BEST_CLOSED] = "closed",
[BEST_DISCONNECTED] = "disconnected",
@@ -219,7 +220,7 @@
list_for_each (ent, &dev_list) {
np = list_entry(ent, struct net_private, list);
if (np->handle == handle)
- return np->dev;
+ return np->netdev;
}
return NULL;
}
@@ -448,7 +449,7 @@
BUG();
}
grant_rx_ref[id] = ref;
- gnttab_grant_foreign_transfer_ref(ref, rdomid,
+ gnttab_grant_foreign_transfer_ref(ref, np->backend_id,
virt_to_mfn(skb->head));
np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.gref = ref;
#endif
@@ -544,7 +545,7 @@
BUG();
}
mfn = virt_to_mfn(skb->data);
- gnttab_grant_foreign_access_ref(ref, rdomid, mfn, GNTMAP_readonly);
+ gnttab_grant_foreign_access_ref(ref, np->backend_id, mfn, GNTMAP_readonly);
tx->addr = ref << PAGE_SHIFT;
grant_tx_ref[id] = ref;
#else
@@ -809,7 +810,7 @@
{
struct net_private *np = netdev_priv(dev);
np->user_state = UST_CLOSED;
- netif_stop_queue(np->dev);
+ netif_stop_queue(np->netdev);
return 0;
}
@@ -821,8 +822,7 @@
}
-static void network_connect(struct net_device *dev,
- netif_fe_interface_status_t *status)
+static void network_connect(struct net_device *dev)
{
struct net_private *np;
int i, requeue_idx;
@@ -890,7 +890,7 @@
*/
np->backend_state = BEST_CONNECTED;
wmb();
- notify_via_evtchn(status->evtchn);
+ notify_via_evtchn(np->evtchn);
network_tx_buf_gc(dev);
if (np->user_state == UST_OPEN)
@@ -900,108 +900,57 @@
spin_unlock_irq(&np->tx_lock);
}
-static void vif_show(struct net_private *np)
+static void show_device(struct net_private *np)
{
#ifdef DEBUG
- if (np) {
- IPRINTK("<vif handle=%u %s(%s) evtchn=%u tx=%p rx=%p>\n",
- np->handle,
- be_state_name[np->backend_state],
- np->user_state ? "open" : "closed",
- np->evtchn,
- np->tx,
- np->rx);
- } else {
- IPRINTK("<vif NULL>\n");
- }
-#endif
-}
-
-/* Send a connect message to xend to tell it to bring up the interface. */
-static void send_interface_connect(struct net_private *np)
-{
- int err;
- ctrl_msg_t cmsg = {
- .type = CMSG_NETIF_FE,
- .subtype = CMSG_NETIF_FE_INTERFACE_CONNECT,
- .length = sizeof(netif_fe_interface_connect_t),
- };
- netif_fe_interface_connect_t *msg = (void*)cmsg.msg;
-
- msg->handle = np->handle;
- msg->tx_shmem_frame = virt_to_mfn(np->tx);
-#ifdef CONFIG_XEN_NETDEV_GRANT_TX
- err = gnttab_grant_foreign_access(rdomid, msg->tx_shmem_frame, 0);
- if (err < 0) {
- printk(KERN_ALERT "#### netfront can't grant access to tx_shmem\n");
- BUG();
- }
- msg->tx_shmem_ref = err;
-#endif
-
- msg->rx_shmem_frame = virt_to_mfn(np->rx);
-#ifdef CONFIG_XEN_NETDEV_GRANT_RX
- err = gnttab_grant_foreign_access(rdomid, msg->rx_shmem_frame, 0);
- if (err < 0) {
- printk(KERN_ALERT "#### netfront can't grant access to rx_shmem\n");
- BUG();
- }
- msg->rx_shmem_ref = err;
-#endif
-
- ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-}
-
-/* Send a driver status notification to the domain controller. */
-static int send_driver_status(int ok)
-{
- int err = 0;
- ctrl_msg_t cmsg = {
- .type = CMSG_NETIF_FE,
- .subtype = CMSG_NETIF_FE_DRIVER_STATUS,
- .length = sizeof(netif_fe_driver_status_t),
- };
- netif_fe_driver_status_t *msg = (void*)cmsg.msg;
-
- msg->status = (ok ? NETIF_DRIVER_STATUS_UP : NETIF_DRIVER_STATUS_DOWN);
- err = ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
- return err;
+ if (np) {
+ IPRINTK("<vif handle=%u %s(%s) evtchn=%u tx=%p rx=%p>\n",
+ np->handle,
+ be_state_name[np->backend_state],
+ np->user_state ? "open" : "closed",
+ np->evtchn,
+ np->tx,
+ np->rx);
+ } else {
+ IPRINTK("<vif NULL>\n");
+ }
+#endif
}
/* Stop network device and free tx/rx queues and irq.
*/
-static void vif_release(struct net_private *np)
-{
- /* Stop old i/f to prevent errors whilst we rebuild the state. */
- spin_lock_irq(&np->tx_lock);
- spin_lock(&np->rx_lock);
- netif_stop_queue(np->dev);
- /* np->backend_state = BEST_DISCONNECTED; */
- spin_unlock(&np->rx_lock);
- spin_unlock_irq(&np->tx_lock);
+static void shutdown_device(struct net_private *np)
+{
+ /* Stop old i/f to prevent errors whilst we rebuild the state. */
+ spin_lock_irq(&np->tx_lock);
+ spin_lock(&np->rx_lock);
+ netif_stop_queue(np->netdev);
+ /* np->backend_state = BEST_DISCONNECTED; */
+ spin_unlock(&np->rx_lock);
+ spin_unlock_irq(&np->tx_lock);
- /* Free resources. */
- if ( np->tx != NULL )
- {
- unbind_evtchn_from_irqhandler(np->evtchn, np->dev);
- free_page((unsigned long)np->tx);
- free_page((unsigned long)np->rx);
- np->evtchn = 0;
- np->tx = NULL;
- np->rx = NULL;
- }
+ /* Free resources. */
+ if (np->tx) {
+ unbind_evtchn_from_irqhandler(np->evtchn, np->netdev);
+ np->evtchn = 0;
+ free_page((unsigned long)np->tx);
+ free_page((unsigned long)np->rx);
+ np->tx = NULL;
+ np->rx = NULL;
+ }
}
/* Release vif resources and close it down completely.
*/
static void vif_close(struct net_private *np)
{
+ BUG();
WPRINTK("Unexpected netif-CLOSED message in state %s\n",
be_state_name[np->backend_state]);
- vif_release(np);
+ shutdown_device(np);
np->backend_state = BEST_CLOSED;
/* todo: take dev down and free. */
- vif_show(np);
+ show_device(np);
}
/* Move the vif into disconnected state.
@@ -1010,6 +959,7 @@
*/
static void vif_disconnect(struct net_private *np)
{
+ BUG();
if(np->tx) free_page((unsigned long)np->tx);
if(np->rx) free_page((unsigned long)np->rx);
// Before this np->tx and np->rx had better be null.
@@ -1018,8 +968,8 @@
memset(np->tx, 0, PAGE_SIZE);
memset(np->rx, 0, PAGE_SIZE);
np->backend_state = BEST_DISCONNECTED;
- send_interface_connect(np);
- vif_show(np);
+ // send_interface_connect(np);
+ show_device(np);
}
/* Begin interface recovery.
@@ -1037,11 +987,12 @@
*/
static void vif_reset(struct net_private *np)
{
+ BUG();
IPRINTK("Attempting to reconnect network interface: handle=%u\n",
np->handle);
- vif_release(np);
+ shutdown_device(np);
vif_disconnect(np);
- vif_show(np);
+ show_device(np);
}
/* Move the vif into connected state.
@@ -1049,20 +1000,17 @@
* Binds the irq to the event channel.
*/
static void
-vif_connect(struct net_private *np, netif_fe_interface_status_t *status)
-{
- struct net_device *dev = np->dev;
- memcpy(dev->dev_addr, status->mac, ETH_ALEN);
- network_connect(dev, status);
- np->evtchn = status->evtchn;
-#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX)
- rdomid = status->domid;
-#endif
+connect_device(struct net_private *np, unsigned int evtchn)
+{
+ struct net_device *dev = np->netdev;
+ memcpy(dev->dev_addr, np->mac, ETH_ALEN);
+ np->evtchn = evtchn;
+ network_connect(dev);
(void)bind_evtchn_to_irqhandler(
np->evtchn, netif_int, SA_SAMPLE_RANDOM, dev->name, dev);
netctrl_connected_count();
(void)send_fake_arp(dev);
- vif_show(np);
+ show_device(np);
}
static struct ethtool_ops network_ethtool_ops =
@@ -1076,22 +1024,24 @@
* @param val return parameter for created device
* @return 0 on success, error code otherwise
*/
-static int create_netdev(int handle, struct net_device **val)
+static int create_netdev(int handle, struct xenbus_device *dev,
+ struct net_device **val)
{
int i, err = 0;
- struct net_device *dev = NULL;
+ struct net_device *netdev = NULL;
struct net_private *np = NULL;
- if ((dev = alloc_etherdev(sizeof(struct net_private))) == NULL) {
+ if ((netdev = alloc_etherdev(sizeof(struct net_private))) == NULL) {
printk(KERN_WARNING "%s> alloc_etherdev failed.\n", __FUNCTION__);
err = -ENOMEM;
goto exit;
}
- np = netdev_priv(dev);
+ np = netdev_priv(netdev);
np->backend_state = BEST_CLOSED;
np->user_state = UST_CLOSED;
np->handle = handle;
+ np->xbdev = dev;
spin_lock_init(&np->tx_lock);
spin_lock_init(&np->rx_lock);
@@ -1115,149 +1065,53 @@
#endif
}
- dev->open = network_open;
- dev->hard_start_xmit = network_start_xmit;
- dev->stop = network_close;
- dev->get_stats = network_get_stats;
- dev->poll = netif_poll;
- dev->weight = 64;
- dev->features = NETIF_F_IP_CSUM;
-
- SET_ETHTOOL_OPS(dev, &network_ethtool_ops);
-
- if ((err = register_netdev(dev)) != 0) {
+ netdev->open = network_open;
+ netdev->hard_start_xmit = network_start_xmit;
+ netdev->stop = network_close;
+ netdev->get_stats = network_get_stats;
+ netdev->poll = netif_poll;
+ netdev->weight = 64;
+ netdev->features = NETIF_F_IP_CSUM;
+
+ SET_ETHTOOL_OPS(netdev, &network_ethtool_ops);
+
+ if ((err = register_netdev(netdev)) != 0) {
printk(KERN_WARNING "%s> register_netdev err=%d\n", __FUNCTION__, err);
goto exit;
}
- if ((err = xennet_proc_addif(dev)) != 0) {
- unregister_netdev(dev);
+ if ((err = xennet_proc_addif(netdev)) != 0) {
+ unregister_netdev(netdev);
goto exit;
}
- np->dev = dev;
+ np->netdev = netdev;
list_add(&np->list, &dev_list);
exit:
- if ((err != 0) && (dev != NULL))
- kfree(dev);
+ if ((err != 0) && (netdev != NULL))
+ kfree(netdev);
else if (val != NULL)
- *val = dev;
+ *val = netdev;
return err;
}
-/* Get the target interface for a status message.
- * Creates the interface when it makes sense.
- * The returned interface may be null when there is no error.
- *
- * @param status status message
- * @param np return parameter for interface state
- * @return 0 on success, error code otherwise
- */
-static int
-target_vif(netif_fe_interface_status_t *status, struct net_private **np)
-{
- int err = 0;
- struct net_device *dev;
-
- DPRINTK("> handle=%d\n", status->handle);
- if (status->handle < 0) {
- err = -EINVAL;
- goto exit;
- }
-
- if ((dev = find_dev_by_handle(status->handle)) != NULL)
- goto exit;
-
- if (status->status == NETIF_INTERFACE_STATUS_CLOSED)
- goto exit;
- if (status->status == NETIF_INTERFACE_STATUS_CHANGED)
- goto exit;
-
- /* It's a new interface in a good state - create it. */
- DPRINTK("> create device...\n");
- if ((err = create_netdev(status->handle, &dev)) != 0)
- goto exit;
-
- netctrl.interface_n++;
-
- exit:
- if (np != NULL)
- *np = ((dev && !err) ? netdev_priv(dev) : NULL);
- DPRINTK("< err=%d\n", err);
- return err;
-}
-
-/* Handle an interface status message. */
-static void netif_interface_status(netif_fe_interface_status_t *status)
-{
- int err = 0;
- struct net_private *np = NULL;
-
- DPRINTK("> status=%s handle=%d\n",
- status_name[status->status], status->handle);
-
- if ((err = target_vif(status, &np)) != 0) {
- WPRINTK("Invalid netif: handle=%u\n", status->handle);
- return;
- }
-
- if (np == NULL) {
- DPRINTK("> no vif\n");
- return;
- }
-
- switch (status->status) {
- case NETIF_INTERFACE_STATUS_CLOSED:
- switch (np->backend_state) {
- case BEST_CLOSED:
- case BEST_DISCONNECTED:
- case BEST_CONNECTED:
- vif_close(np);
- break;
- }
- break;
-
- case NETIF_INTERFACE_STATUS_DISCONNECTED:
- switch (np->backend_state) {
- case BEST_CLOSED:
- vif_disconnect(np);
- break;
- case BEST_DISCONNECTED:
- case BEST_CONNECTED:
- vif_reset(np);
- break;
- }
- break;
-
- case NETIF_INTERFACE_STATUS_CONNECTED:
- switch (np->backend_state) {
- case BEST_CLOSED:
- WPRINTK("Unexpected netif status %s in state %s\n",
- status_name[status->status],
- be_state_name[np->backend_state]);
- vif_disconnect(np);
- vif_connect(np, status);
- break;
- case BEST_DISCONNECTED:
- vif_connect(np, status);
- break;
- }
- break;
-
- case NETIF_INTERFACE_STATUS_CHANGED:
- /*
- * The domain controller is notifying us that a device has been
- * added or removed.
- */
- break;
-
- default:
- WPRINTK("Invalid netif status code %d\n", status->status);
- break;
- }
-
- vif_show(np);
+static int destroy_netdev(struct net_device *netdev)
+{
+ struct net_private *np = NULL;
+
+#ifdef CONFIG_PROC_FS
+ xennet_proc_delif(netdev);
+#endif
+
+ unregister_netdev(netdev);
+
+ np = netdev_priv(netdev);
+ list_del(&np->list);
+
+ kfree(netdev);
+
+ return 0;
}
/*
@@ -1268,115 +1122,6 @@
netctrl.up = status->status;
netctrl_connected_count();
}
-
-/* Receive handler for control messages. */
-static void netif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
-{
-
- switch (msg->subtype) {
- case CMSG_NETIF_FE_INTERFACE_STATUS:
- netif_interface_status((netif_fe_interface_status_t *) &msg->msg[0]);
- break;
-
- case CMSG_NETIF_FE_DRIVER_STATUS:
- netif_driver_status((netif_fe_driver_status_t *) &msg->msg[0]);
- break;
-
- default:
- msg->length = 0;
- break;
- }
-
- ctrl_if_send_response(msg);
-}
-
-
-#if 1
-/* Wait for all interfaces to be connected.
- *
- * This works OK, but we'd like to use the probing mode (see below).
- */
-static int probe_interfaces(void)
-{
- int err = 0, conn = 0;
- int wait_i, wait_n = 100;
-
- DPRINTK(">\n");
-
- for (wait_i = 0; wait_i < wait_n; wait_i++) {
- DPRINTK("> wait_i=%d\n", wait_i);
- conn = netctrl_connected();
- if(conn) break;
- DPRINTK("> schedule_timeout...\n");
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(10);
- }
-
- DPRINTK("> wait finished...\n");
- if (conn <= 0) {
- err = netctrl_err(-ENETDOWN);
- WPRINTK("Failed to connect all virtual interfaces: err=%d\n", err);
- }
-
- DPRINTK("< err=%d\n", err);
-
- return err;
-}
-#else
-/* Probe for interfaces until no more are found.
- *
- * This is the mode we'd like to use, but at the moment it panics the kernel.
-*/
-static int probe_interfaces(void)
-{
- int err = 0;
- int wait_i, wait_n = 100;
- ctrl_msg_t cmsg = {
- .type = CMSG_NETIF_FE,
- .subtype = CMSG_NETIF_FE_INTERFACE_STATUS,
- .length = sizeof(netif_fe_interface_status_t),
- };
- netif_fe_interface_status_t msg = {};
- ctrl_msg_t rmsg = {};
- netif_fe_interface_status_t *reply = (void*)rmsg.msg;
- int state = TASK_UNINTERRUPTIBLE;
- u32 query = -1;
-
- DPRINTK(">\n");
-
- netctrl.interface_n = 0;
- for (wait_i = 0; wait_i < wait_n; wait_i++) {
- DPRINTK("> wait_i=%d query=%d\n", wait_i, query);
- msg.handle = query;
- memcpy(cmsg.msg, &msg, sizeof(msg));
- DPRINTK("> set_current_state...\n");
- set_current_state(state);
- DPRINTK("> rmsg=%p msg=%p, reply=%p\n", &rmsg, rmsg.msg, reply);
- DPRINTK("> sending...\n");
- err = ctrl_if_send_message_and_get_response(&cmsg, &rmsg, state);
- DPRINTK("> err=%d\n", err);
- if(err) goto exit;
- DPRINTK("> rmsg=%p msg=%p, reply=%p\n", &rmsg, rmsg.msg, reply);
- if((int)reply->handle < 0) {
- // No more interfaces.
- break;
- }
- query = -reply->handle - 2;
- DPRINTK(">netif_interface_status ...\n");
- netif_interface_status(reply);
- }
-
- exit:
- if (err) {
- err = netctrl_err(-ENETDOWN);
- WPRINTK("Connecting virtual network interfaces failed: err=%d\n", err);
- }
-
- DPRINTK("< err=%d\n", err);
- return err;
-}
-
-#endif
/*
* We use this notifier to send out a fake ARP reply to reset switches and
@@ -1395,7 +1140,7 @@
list_for_each (ent, &dev_list) {
np = list_entry(ent, struct net_private, list);
- if (np->dev == dev)
+ if (np->netdev == dev)
(void)send_fake_arp(dev);
}
@@ -1409,67 +1154,317 @@
.priority = 0
};
-static int __init netif_init(void)
-{
- int err = 0;
-
- if (xen_start_info.flags & SIF_INITDOMAIN)
- return 0;
+static struct xenbus_device_id netfront_ids[] = {
+ { "vif" },
+ { "" }
+};
+
+static void watch_for_status(struct xenbus_watch *watch, const char *node)
+{
+#if 0
+ struct netfront_info *info;
+ unsigned int binfo;
+ unsigned long sectors, sector_size;
+ int err;
+
+ info = container_of(watch, struct netfront_info, watch);
+ node += strlen(watch->node);
+
+ /* FIXME: clean up when error on the other end. */
+ if (info->connected == BLKIF_STATE_CONNECTED)
+ return;
+
+ err = xenbus_gather(watch->node,
+ "sectors", "%lu", §ors,
+ "info", "%u", &binfo,
+ "sector-size", "%lu", §or_size,
+ NULL);
+ if (err) {
+ xenbus_dev_error(info->xbdev, err, "reading backend fields");
+ return;
+ }
+
+ xlvbd_add(sectors, info->vdevice, binfo, sector_size, info);
+ info->connected = BLKIF_STATE_CONNECTED;
+
+ blkif_state = BLKIF_STATE_CONNECTED;
+
+ xenbus_dev_ok(info->xbdev);
+
+ /* Kick pending requests. */
+ spin_lock_irq(&blkif_io_lock);
+ kick_pending_request_queues(info);
+ spin_unlock_irq(&blkif_io_lock);
+#endif
+}
+
+static int setup_device(struct xenbus_device *dev, struct netfront_info *info)
+{
+ evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound };
+ int err;
+
#ifdef CONFIG_XEN_NETDEV_GRANT_TX
- /* A grant for every ring slot */
- if (gnttab_alloc_grant_references(NETIF_TX_RING_SIZE,
- &gref_tx_head) < 0) {
- printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n");
- return 1;
- }
- printk(KERN_ALERT "Netdev frontend (TX) is using grant tables.\n");
+ info->tx_ring_ref = GRANT_INVALID_REF;
#endif
#ifdef CONFIG_XEN_NETDEV_GRANT_RX
- /* A grant for every ring slot */
- if (gnttab_alloc_grant_references(NETIF_RX_RING_SIZE,
- &gref_rx_head) < 0) {
- printk(KERN_ALERT "#### netfront can't alloc rx grant refs\n");
- return 1;
- }
- printk(KERN_ALERT "Netdev frontend (RX) is using grant tables.\n");
-#endif
-
- if ((err = xennet_proc_init()) != 0)
- return err;
-
- IPRINTK("Initialising virtual ethernet driver.\n");
- INIT_LIST_HEAD(&dev_list);
- (void)register_inetaddr_notifier(¬ifier_inetdev);
- netctrl_init();
- (void)ctrl_if_register_receiver(CMSG_NETIF_FE, netif_ctrlif_rx,
- CALLBACK_IN_BLOCKING_CONTEXT);
- send_driver_status(1);
- err = probe_interfaces();
- if (err)
- ctrl_if_unregister_receiver(CMSG_NETIF_FE, netif_ctrlif_rx);
-
- DPRINTK("< err=%d\n", err);
- return err;
-}
-
-static void netif_exit(void)
-{
+ info->rx_ring_ref = GRANT_INVALID_REF;
+#endif
+
+ info->tx = (netif_tx_interface_t *)__get_free_page(GFP_KERNEL);
+ if (info->tx == 0) {
+ err = -ENOMEM;
+ xenbus_dev_error(dev, err, "allocating tx ring page");
+ goto out;
+ }
+ info->rx = (netif_rx_interface_t *)__get_free_page(GFP_KERNEL);
+ if (info->rx == 0) {
+ err = -ENOMEM;
+ xenbus_dev_error(dev, err, "allocating rx ring page");
+ goto out;
+ }
+ memset(info->tx, 0, PAGE_SIZE);
+ memset(info->rx, 0, PAGE_SIZE);
+ info->backend_state = BEST_DISCONNECTED;
+
#ifdef CONFIG_XEN_NETDEV_GRANT_TX
- gnttab_free_grant_references(gref_tx_head);
-#endif
+ err = gnttab_grant_foreign_access(info->backend_id,
+ virt_to_mfn(info->tx), 0);
+ if (err < 0) {
+ xenbus_dev_error(dev, err, "granting access to tx ring page");
+ goto out;
+ }
+ info->tx_ring_ref = err;
+#else
+ info->tx_ring_ref = virt_to_mfn(info->tx);
+#endif
+
#ifdef CONFIG_XEN_NETDEV_GRANT_RX
- gnttab_free_grant_references(gref_rx_head);
-#endif
-}
-
-static void vif_suspend(struct net_private *np)
-{
+ err = gnttab_grant_foreign_access(info->backend_id,
+ virt_to_mfn(info->rx), 0);
+ if (err < 0) {
+ xenbus_dev_error(dev, err, "granting access to rx ring page");
+ goto out;
+ }
+ info->rx_ring_ref = err;
+#else
+ info->rx_ring_ref = virt_to_mfn(info->rx);
+#endif
+
+ op.u.alloc_unbound.dom = info->backend_id;
+ err = HYPERVISOR_event_channel_op(&op);
+ if (err) {
+ xenbus_dev_error(dev, err, "allocating event channel");
+ goto out;
+ }
+ connect_device(info, op.u.alloc_unbound.port);
+ return 0;
+
+ out:
+ if (info->tx)
+ free_page((unsigned long)info->tx);
+ info->tx = 0;
+ if (info->rx)
+ free_page((unsigned long)info->rx);
+ info->rx = 0;
+#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+ if (info->tx_ring_ref != GRANT_INVALID_REF)
+ gnttab_end_foreign_access(info->tx_ring_ref, 0);
+ info->tx_ring_ref = GRANT_INVALID_REF;
+#endif
+#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+ if (info->rx_ring_ref != GRANT_INVALID_REF)
+ gnttab_end_foreign_access(info->rx_ring_ref, 0);
+ info->rx_ring_ref = GRANT_INVALID_REF;
+#endif
+ return err;
+}
+
+/* Common code used when first setting up, and when resuming. */
+static int talk_to_backend(struct xenbus_device *dev,
+ struct netfront_info *info)
+{
+ char *backend, *mac, *e, *s;
+ const char *message;
+ int err, i;
+
+ backend = NULL;
+ err = xenbus_gather(dev->nodename,
+ "backend-id", "%i", &info->backend_id,
+ "backend", NULL, &backend,
+ NULL);
+ if (XENBUS_EXIST_ERR(err))
+ goto out;
+ if (backend && strlen(backend) == 0) {
+ err = -ENOENT;
+ goto out;
+ }
+ if (err < 0) {
+ xenbus_dev_error(dev, err, "reading %s/backend or backend-id",
+ dev->nodename);
+ goto out;
+ }
+
+ mac = xenbus_read(dev->nodename, "mac", NULL);
+ if (IS_ERR(mac)) {
+ err = PTR_ERR(mac);
+ xenbus_dev_error(dev, err, "reading %s/mac",
+ dev->nodename);
+ goto out;
+ }
+ s = mac;
+ for (i = 0; i < ETH_ALEN; i++) {
+ info->mac[i] = simple_strtoul(s, &e, 16);
+ if (s == e || (e[0] != ':' && e[0] != 0)) {
+ kfree(mac);
+ err = -ENOENT;
+ xenbus_dev_error(dev, err, "parsing %s/mac",
+ dev->nodename);
+ goto out;
+ }
+ s = &e[1];
+ }
+ kfree(mac);
+
+ /* Create shared ring, alloc event channel. */
+ err = setup_device(dev, info);
+ if (err) {
+ xenbus_dev_error(dev, err, "setting up ring");
+ goto out;
+ }
+
+ err = xenbus_transaction_start(dev->nodename);
+ if (err) {
+ xenbus_dev_error(dev, err, "starting transaction");
+ goto destroy_ring;
+ }
+
+ err = xenbus_printf(dev->nodename, "tx-ring-ref","%u",
+ info->tx_ring_ref);
+ if (err) {
+ message = "writing tx ring-ref";
+ goto abort_transaction;
+ }
+ err = xenbus_printf(dev->nodename, "rx-ring-ref","%u",
+ info->rx_ring_ref);
+ if (err) {
+ message = "writing rx ring-ref";
+ goto abort_transaction;
+ }
+ err = xenbus_printf(dev->nodename,
+ "event-channel", "%u", info->evtchn);
+ if (err) {
+ message = "writing event-channel";
+ goto abort_transaction;
+ }
+
+ info->backend = backend;
+ backend = NULL;
+
+ info->watch.node = info->backend;
+ info->watch.callback = watch_for_status;
+ err = register_xenbus_watch(&info->watch);
+ if (err) {
+ message = "registering watch on backend";
+ goto abort_transaction;
+ }
+
+ err = xenbus_transaction_end(0);
+ if (err) {
+ xenbus_dev_error(dev, err, "completing transaction");
+ goto destroy_ring;
+ }
+
+ out:
+ if (backend)
+ kfree(backend);
+ return err;
+
+ abort_transaction:
+ xenbus_transaction_end(1);
+ /* Have to do this *outside* transaction. */
+ xenbus_dev_error(dev, err, "%s", message);
+ destroy_ring:
+ shutdown_device(info);
+ goto out;
+}
+
+/* Setup supplies the backend dir, virtual device.
+
+ We place an event channel and shared frame entries.
+ We watch backend to wait if it's ok. */
+static int netfront_probe(struct xenbus_device *dev,
+ const struct xenbus_device_id *id)
+{
+ int err;
+ struct net_device *netdev;
+ unsigned int handle;
+
+ printk("netfront_probe %p\n", dev);
+ err = xenbus_scanf(dev->nodename, "handle", "%u", &handle);
+ if (XENBUS_EXIST_ERR(err))
+ return err;
+ if (err < 0) {
+ xenbus_dev_error(dev, err, "reading handle");
+ return err;
+ }
+
+ printk("netfront_probe handle %d\n", handle);
+ netdev = find_dev_by_handle(handle);
+ printk("netfront_probe found netdev %p\n", netdev);
+ if (netdev)
+ return 0;
+
+ err = create_netdev(handle, dev, &netdev);
+ if (err) {
+ xenbus_dev_error(dev, err, "creating netdev");
+ return err;
+ }
+
+ printk("netfront_probe netdev %p\n", netdev);
+ err = talk_to_backend(dev, netdev_priv(netdev));
+ if (err) {
+ destroy_netdev(netdev);
+ return err;
+ }
+
+#if 0
+ /* Call once in case entries already there. */
+ watch_for_status(&info->watch, info->watch.node);
+#endif
+ return 0;
+}
+
+static int netfront_remove(struct xenbus_device *dev)
+{
+ struct netfront_info *info = dev->data;
+
+#if 0
+ if (info->backend)
+ unregister_xenbus_watch(&info->watch);
+
+ if (info->mi)
+ xlvbd_del(info);
+
+ blkif_free(info);
+
+ kfree(info->backend);
+#endif
+ kfree(info);
+
+ return 0;
+}
+
+static int netfront_suspend(struct xenbus_device *dev)
+{
+ struct net_private *np = dev->data;
/* Avoid having tx/rx stuff happen until we're ready. */
- unbind_evtchn_from_irqhandler(np->evtchn, np->dev);
-}
-
-static void vif_resume(struct net_private *np)
-{
+ unbind_evtchn_from_irqhandler(np->evtchn, np->netdev);
+ return 0;
+}
+
+static int netfront_resume(struct xenbus_device *dev)
+{
+ struct net_private *np = dev->data;
/*
* Connect regardless of whether IFF_UP flag set.
* Stop bad things from happening until we're back up.
@@ -1478,29 +1473,101 @@
memset(np->tx, 0, PAGE_SIZE);
memset(np->rx, 0, PAGE_SIZE);
- send_interface_connect(np);
-}
-
-void netif_suspend(void)
-{
- struct list_head *ent;
- struct net_private *np;
-
- list_for_each (ent, &dev_list) {
- np = list_entry(ent, struct net_private, list);
- vif_suspend(np);
- }
-}
-
-void netif_resume(void)
-{
- struct list_head *ent;
- struct net_private *np;
-
- list_for_each (ent, &dev_list) {
- np = list_entry(ent, struct net_private, list);
- vif_resume(np);
- }
+ // send_interface_connect(np);
+ return 0;
+}
+
+static struct xenbus_driver netfront = {
+ .name = "vif",
+ .owner = THIS_MODULE,
+ .ids = netfront_ids,
+ .probe = netfront_probe,
+ .remove = netfront_remove,
+ .resume = netfront_resume,
+ .suspend = netfront_suspend,
+};
+
+static void __init init_net_xenbus(void)
+{
+ xenbus_register_device(&netfront);
+}
+
+static int wait_for_netif(void)
+{
+ int err = 0, conn = 0;
+ int i;
+
+ /*
+ * We should figure out how many and which devices we need to
+ * proceed and only wait for those. For now, continue once the
+ * first device is around.
+ */
+ for ( i=0; i < 10*HZ; i++ )
+ {
+ conn = netctrl_connected();
+ if (conn)
+ break;
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ }
+
+ if (conn <= 0) {
+ err = netctrl_err(-ENETDOWN);
+ WPRINTK("Timeout connecting to device!\n");
+ }
+ return err;
+}
+
+static int __init netif_init(void)
+{
+ int err = 0;
+
+ if (xen_start_info.flags & SIF_INITDOMAIN)
+ return 0;
+
+#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+ /* A grant for every ring slot */
+ if (gnttab_alloc_grant_references(NETIF_TX_RING_SIZE,
+ &gref_tx_head) < 0) {
+ printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n");
+ return 1;
+ }
+ printk(KERN_ALERT "Netdev frontend (TX) is using grant tables.\n");
+#endif
+#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+ /* A grant for every ring slot */
+ if (gnttab_alloc_grant_references(NETIF_RX_RING_SIZE,
+ &gref_rx_head) < 0) {
+ printk(KERN_ALERT "#### netfront can't alloc rx grant refs\n");
+ return 1;
+ }
+ printk(KERN_ALERT "Netdev frontend (RX) is using grant tables.\n");
+#endif
+
+ if ((err = xennet_proc_init()) != 0)
+ return err;
+
+ IPRINTK("Initialising virtual ethernet driver.\n");
+
+ INIT_LIST_HEAD(&dev_list);
+ (void)register_inetaddr_notifier(¬ifier_inetdev);
+ netctrl_init();
+
+ init_net_xenbus();
+
+ wait_for_netif();
+
+ return err;
+}
+
+static void netif_exit(void)
+{
+#ifdef CONFIG_XEN_NETDEV_GRANT_TX
+ gnttab_free_grant_references(gref_tx_head);
+#endif
+#ifdef CONFIG_XEN_NETDEV_GRANT_RX
+ gnttab_free_grant_references(gref_rx_head);
+#endif
}
#ifdef CONFIG_PROC_FS
diff -r d4ce28d819a8 -r b402e77aac46 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Wed Aug 24 22:21:24 2005
+++ b/tools/python/xen/xend/XendDomainInfo.py Wed Aug 24 22:22:11 2005
@@ -265,6 +265,8 @@
self.info = None
self.blkif_backend = False
self.netif_backend = False
+ self.netif_idx = 0
+
#todo: state: running, suspended
self.state = STATE_VM_OK
self.state_updated = threading.Condition()
@@ -400,8 +402,7 @@
db['virtual-device'] = "%i" % devnum
#db['backend'] = sxp.child_value(devconfig, 'backend', '0')
db['backend'] = backdb.getPath()
- db['backend-id'] = "%i" % int(sxp.child_value(devconfig,
- 'backend', '0'))
+ db['backend-id'] = "%i" % backdom.id
backdb['frontend'] = db.getPath()
(type, params) = string.split(sxp.child_value(devconfig, 'uname'),
':', 1)
@@ -417,6 +418,37 @@
db.saveDB(save=True)
return
+
+ if type == 'vif':
+ backdom = domain_exists(sxp.child_value(devconfig, 'backend', '0'))
+
+ log.error(devconfig)
+
+ devnum = self.netif_idx
+ self.netif_idx += 1
+
+ # create backend db
+ backdb = backdom.db.addChild("/backend/%s/%s/%d" %
+ (type, self.uuid, devnum))
+
+ # create frontend db
+ db = self.db.addChild("/device/%s/%d" % (type, devnum))
+
+ backdb['frontend'] = db.getPath()
+ backdb['frontend-id'] = "%i" % self.id
+ backdb['handle'] = "%i" % devnum
+ backdb.saveDB(save=True)
+
+ db['backend'] = backdb.getPath()
+ db['backend-id'] = "%i" % backdom.id
+ db['handle'] = "%i" % devnum
+ log.error(sxp.child_value(devconfig, 'mac'))
+ db['mac'] = sxp.child_value(devconfig, 'mac')
+
+ db.saveDB(save=True)
+
+ return
+
ctrl = self.findDeviceController(type)
return ctrl.createDevice(devconfig, recreate=self.recreate,
change=change)
diff -r d4ce28d819a8 -r b402e77aac46
linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c
--- /dev/null Wed Aug 24 22:21:24 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Wed Aug 24 22:22:11 2005
@@ -0,0 +1,323 @@
+/* Xenbus code for netif backend
+ Copyright (C) 2005 Rusty Russell <rusty@xxxxxxxxxxxxxxx>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+#include <stdarg.h>
+#include <linux/module.h>
+#include <asm-xen/xenbus.h>
+#include "common.h"
+
+struct backend_info
+{
+ struct xenbus_device *dev;
+
+ /* our communications channel */
+ netif_t *netif;
+
+ long int frontend_id;
+#if 0
+ long int pdev;
+ long int readonly;
+#endif
+
+ /* watch back end for changes */
+ struct xenbus_watch backend_watch;
+
+ /* watch front end for changes */
+ struct xenbus_watch watch;
+ char *frontpath;
+};
+
+static int netback_remove(struct xenbus_device *dev)
+{
+ struct backend_info *be = dev->data;
+
+ if (be->watch.node)
+ unregister_xenbus_watch(&be->watch);
+ unregister_xenbus_watch(&be->backend_watch);
+#if 0
+ if (be->blkif)
+ blkif_put(be->blkif);
+#endif
+ if (be->frontpath)
+ kfree(be->frontpath);
+ kfree(be);
+ return 0;
+}
+
+/* Front end tells us frame. */
+static void frontend_changed(struct xenbus_watch *watch, const char *node)
+{
+ unsigned long tx_ring_ref, rx_ring_ref;
+ unsigned int evtchn;
+ int err;
+ struct backend_info *be
+ = container_of(watch, struct backend_info, watch);
+ char *mac, *e, *s;
+ int i;
+
+ /* If other end is gone, delete ourself. */
+ if (node && !xenbus_exists(be->frontpath, "")) {
+ xenbus_rm(be->dev->nodename, "");
+ device_unregister(&be->dev->dev);
+ return;
+ }
+ if (be->netif == NULL || be->netif->status == CONNECTED)
+ return;
+
+ mac = xenbus_read(be->frontpath, "mac", NULL);
+ if (IS_ERR(mac)) {
+ err = PTR_ERR(mac);
+ xenbus_dev_error(be->dev, err, "reading %s/mac",
+ be->dev->nodename);
+ return;
+ }
+ s = mac;
+ for (i = 0; i < ETH_ALEN; i++) {
+ be->netif->fe_dev_addr[i] = simple_strtoul(s, &e, 16);
+ if (s == e || (e[0] != ':' && e[0] != 0)) {
+ kfree(mac);
+ err = -ENOENT;
+ xenbus_dev_error(be->dev, err, "parsing %s/mac",
+ be->dev->nodename);
+ return;
+ }
+ s = &e[1];
+ }
+ kfree(mac);
+
+ err = xenbus_gather(be->frontpath, "tx-ring-ref", "%lu", &tx_ring_ref,
+ "rx-ring-ref", "%lu", &rx_ring_ref,
+ "event-channel", "%u", &evtchn, NULL);
+ if (err) {
+ xenbus_dev_error(be->dev, err,
+ "reading %s/ring-ref and event-channel",
+ be->frontpath);
+ return;
+ }
+
+#if 0
+ /* Supply the information about the device the frontend needs */
+ err = xenbus_transaction_start(be->dev->nodename);
+ if (err) {
+ xenbus_dev_error(be->dev, err, "starting transaction");
+ return;
+ }
+
+ err = xenbus_printf(be->dev->nodename, "sectors", "%lu",
+ vbd_size(&be->blkif->vbd));
+ if (err) {
+ xenbus_dev_error(be->dev, err, "writing %s/sectors",
+ be->dev->nodename);
+ goto abort;
+ }
+
+ /* FIXME: use a typename instead */
+ err = xenbus_printf(be->dev->nodename, "info", "%u",
+ vbd_info(&be->blkif->vbd));
+ if (err) {
+ xenbus_dev_error(be->dev, err, "writing %s/info",
+ be->dev->nodename);
+ goto abort;
+ }
+ err = xenbus_printf(be->dev->nodename, "sector-size", "%lu",
+ vbd_secsize(&be->blkif->vbd));
+ if (err) {
+ xenbus_dev_error(be->dev, err, "writing %s/sector-size",
+ be->dev->nodename);
+ goto abort;
+ }
+#endif
+
+ /* Map the shared frame, irq etc. */
+ err = netif_map(be->netif, tx_ring_ref, rx_ring_ref, evtchn);
+ if (err) {
+ xenbus_dev_error(be->dev, err,
+ "mapping shared-frames %lu/%lu port %u",
+ tx_ring_ref, rx_ring_ref, evtchn);
+ goto abort;
+ }
+
+#if 0
+ xenbus_transaction_end(0);
+#endif
+ xenbus_dev_ok(be->dev);
+
+ return;
+
+abort:
+ // xenbus_transaction_end(1);
+ ;
+}
+
+/*
+ Setup supplies physical device.
+ We provide event channel and device details to front end.
+ Frontend supplies shared frame and event channel.
+ */
+static void backend_changed(struct xenbus_watch *watch, const char *node)
+{
+ int err;
+ char *p;
+ long int handle, pdev;
+ struct backend_info *be
+ = container_of(watch, struct backend_info, backend_watch);
+ struct xenbus_device *dev = be->dev;
+ u8 be_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
+
+ err = xenbus_scanf(dev->nodename, "handle", "%li", &handle);
+ if (XENBUS_EXIST_ERR(err))
+ return;
+ if (err < 0) {
+ xenbus_dev_error(dev, err, "reading handle");
+ return;
+ }
+
+#if 0
+ err = xenbus_scanf(dev->nodename, "physical-device", "%li", &pdev);
+ if (XENBUS_EXIST_ERR(err))
+ return;
+ if (err < 0) {
+ xenbus_dev_error(dev, err, "reading physical-device");
+ return;
+ }
+ if (be->pdev && be->pdev != pdev) {
+ printk(KERN_WARNING
+ "changing physical-device not supported\n");
+ return;
+ }
+ be->pdev = pdev;
+
+ /* If there's a read-only node, we're read only. */
+ p = xenbus_read(dev->nodename, "read-only", NULL);
+ if (!IS_ERR(p)) {
+ be->readonly = 1;
+ kfree(p);
+ }
+#endif
+
+ if (be->netif == NULL) {
+ be->netif = alloc_netif(be->frontend_id, handle, be_mac);
+ if (IS_ERR(be->netif)) {
+ err = PTR_ERR(be->netif);
+ be->netif = NULL;
+ xenbus_dev_error(dev, err, "creating interface");
+ return;
+ }
+
+#if 0
+ err = vbd_create(be->netif, handle, be->pdev, be->readonly);
+ if (err) {
+ xenbus_dev_error(dev, err, "creating vbd structure");
+ return;
+ }
+#endif
+
+ /* Pass in NULL node to skip exist test. */
+ frontend_changed(&be->watch, NULL);
+ }
+}
+
+static int netback_probe(struct xenbus_device *dev,
+ const struct xenbus_device_id *id)
+{
+ struct backend_info *be;
+ char *frontend;
+ int err;
+
+ be = kmalloc(sizeof(*be), GFP_KERNEL);
+ if (!be) {
+ xenbus_dev_error(dev, -ENOMEM, "allocating backend structure");
+ return -ENOMEM;
+ }
+ memset(be, 0, sizeof(*be));
+
+ frontend = NULL;
+ err = xenbus_gather(dev->nodename,
+ "frontend-id", "%li", &be->frontend_id,
+ "frontend", NULL, &frontend,
+ NULL);
+ if (XENBUS_EXIST_ERR(err))
+ goto free_be;
+ if (err < 0) {
+ xenbus_dev_error(dev, err,
+ "reading %s/frontend or frontend-id",
+ dev->nodename);
+ goto free_be;
+ }
+ if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
+ /* If we can't get a frontend path and a frontend-id,
+ * then our bus-id is no longer valid and we need to
+ * destroy the backend device.
+ */
+ err = -ENOENT;
+ goto free_be;
+ }
+
+ be->dev = dev;
+ be->backend_watch.node = dev->nodename;
+ be->backend_watch.callback = backend_changed;
+ err = register_xenbus_watch(&be->backend_watch);
+ if (err) {
+ be->backend_watch.node = NULL;
+ xenbus_dev_error(dev, err, "adding backend watch on %s",
+ dev->nodename);
+ goto free_be;
+ }
+
+ be->frontpath = frontend;
+ be->watch.node = be->frontpath;
+ be->watch.callback = frontend_changed;
+ err = register_xenbus_watch(&be->watch);
+ if (err) {
+ be->watch.node = NULL;
+ xenbus_dev_error(dev, err,
+ "adding frontend watch on %s",
+ be->frontpath);
+ goto free_be;
+ }
+
+ dev->data = be;
+
+ backend_changed(&be->backend_watch, dev->nodename);
+ return 0;
+
+ free_be:
+ if (be->backend_watch.node)
+ unregister_xenbus_watch(&be->backend_watch);
+ if (frontend)
+ kfree(frontend);
+ kfree(be);
+ return err;
+}
+
+static struct xenbus_device_id netback_ids[] = {
+ { "vif" },
+ { "" }
+};
+
+static struct xenbus_driver netback = {
+ .name = "vif",
+ .owner = THIS_MODULE,
+ .ids = netback_ids,
+ .probe = netback_probe,
+ .remove = netback_remove,
+};
+
+void netif_xenbus_init(void)
+{
+ xenbus_register_backend(&netback);
+}
diff -r d4ce28d819a8 -r b402e77aac46
linux-2.6-xen-sparse/drivers/xen/netback/control.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/control.c Wed Aug 24
22:21:24 2005
+++ /dev/null Wed Aug 24 22:22:11 2005
@@ -1,58 +0,0 @@
-/******************************************************************************
- * arch/xen/drivers/netif/backend/control.c
- *
- * Routines for interfacing with the control plane.
- *
- * Copyright (c) 2004, Keir Fraser
- */
-
-#include "common.h"
-
-static void netif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
-{
- DPRINTK("Received netif backend message, subtype=%d\n", msg->subtype);
-
- switch ( msg->subtype )
- {
- case CMSG_NETIF_BE_CREATE:
- netif_create((netif_be_create_t *)&msg->msg[0]);
- break;
- case CMSG_NETIF_BE_DESTROY:
- netif_destroy((netif_be_destroy_t *)&msg->msg[0]);
- break;
- case CMSG_NETIF_BE_CREDITLIMIT:
- netif_creditlimit((netif_be_creditlimit_t *)&msg->msg[0]);
- break;
- case CMSG_NETIF_BE_CONNECT:
- netif_connect((netif_be_connect_t *)&msg->msg[0]);
- break;
- case CMSG_NETIF_BE_DISCONNECT:
- if ( !netif_disconnect((netif_be_disconnect_t *)&msg->msg[0],msg->id) )
- return; /* Sending the response is deferred until later. */
- break;
- default:
- DPRINTK("Parse error while reading message subtype %d, len %d\n",
- msg->subtype, msg->length);
- msg->length = 0;
- break;
- }
-
- ctrl_if_send_response(msg);
-}
-
-void netif_ctrlif_init(void)
-{
- ctrl_msg_t cmsg;
- netif_be_driver_status_t st;
-
- (void)ctrl_if_register_receiver(CMSG_NETIF_BE, netif_ctrlif_rx,
- CALLBACK_IN_BLOCKING_CONTEXT);
-
- /* Send a driver-UP notification to the domain controller. */
- cmsg.type = CMSG_NETIF_BE;
- cmsg.subtype = CMSG_NETIF_BE_DRIVER_STATUS;
- cmsg.length = sizeof(netif_be_driver_status_t);
- st.status = NETIF_DRIVER_STATUS_UP;
- memcpy(cmsg.msg, &st, sizeof(st));
- ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-}
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|