aboutsummaryrefslogtreecommitdiffstats
path: root/linux-2.4.26-xen-sparse
diff options
context:
space:
mode:
authorcl349@freefall.cl.cam.ac.uk <cl349@freefall.cl.cam.ac.uk>2004-07-31 16:13:15 +0000
committercl349@freefall.cl.cam.ac.uk <cl349@freefall.cl.cam.ac.uk>2004-07-31 16:13:15 +0000
commit18f29ff781a8961e61a80abfe460c335401a4ab6 (patch)
treee6c30950674d6e7ca9b6510db6106827f4825ef5 /linux-2.4.26-xen-sparse
parentff2b591309e31b2f3fa275e9da79d55e0414719d (diff)
downloadxen-18f29ff781a8961e61a80abfe460c335401a4ab6.tar.gz
xen-18f29ff781a8961e61a80abfe460c335401a4ab6.tar.bz2
xen-18f29ff781a8961e61a80abfe460c335401a4ab6.zip
bitkeeper revision 1.1108.33.20 (410bc51bu4HGQYf4dl0npPACAL5Irw)
share backend network driver between Linux 2.4 and 2.6
Diffstat (limited to 'linux-2.4.26-xen-sparse')
-rw-r--r--linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/common.h95
-rw-r--r--linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/control.c65
-rw-r--r--linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/interface.c282
-rw-r--r--linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/main.c775
-rwxr-xr-xlinux-2.4.26-xen-sparse/mkbuildtree6
5 files changed, 6 insertions, 1217 deletions
diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/common.h b/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/common.h
deleted file mode 100644
index 87fdb730d1..0000000000
--- a/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/common.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/******************************************************************************
- * arch/xen/drivers/netif/backend/common.h
- */
-
-#ifndef __NETIF__BACKEND__COMMON_H__
-#define __NETIF__BACKEND__COMMON_H__
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/ip.h>
-#include <linux/in.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <asm/ctrl_if.h>
-#include <asm/io.h>
-#include "../netif.h"
-
-#if 0
-#define ASSERT(_p) \
- if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
- __LINE__, __FILE__); *(int*)0=0; }
-#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
- __FILE__ , __LINE__ , ## _a )
-#else
-#define ASSERT(_p) ((void)0)
-#define DPRINTK(_f, _a...) ((void)0)
-#endif
-
-typedef struct netif_st {
- /* Unique identifier for this interface. */
- domid_t domid;
- unsigned int handle;
-
- /* Physical parameters of the comms window. */
- unsigned long tx_shmem_frame;
- unsigned long rx_shmem_frame;
- unsigned int evtchn;
- int irq;
-
- /* The shared rings and indexes. */
- netif_tx_interface_t *tx;
- netif_rx_interface_t *rx;
-
- /* Private indexes into shared ring. */
- NETIF_RING_IDX rx_req_cons;
- NETIF_RING_IDX rx_resp_prod; /* private version of shared variable */
- NETIF_RING_IDX tx_req_cons;
- NETIF_RING_IDX tx_resp_prod; /* private version of shared variable */
-
- /* Transmit shaping: allow 'credit_bytes' every 'credit_usec'. */
- unsigned long credit_bytes;
- unsigned long credit_usec;
- unsigned long remaining_credit;
- struct timer_list credit_timeout;
-
- /* Miscellaneous private stuff. */
- enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
- /*
- * DISCONNECT response is deferred until pending requests are ack'ed.
- * We therefore need to store the id from the original request.
- */
- u8 disconnect_rspid;
- struct netif_st *hash_next;
- struct list_head list; /* scheduling list */
- atomic_t refcnt;
- spinlock_t rx_lock, tx_lock;
- struct net_device *dev;
- struct net_device_stats stats;
-} netif_t;
-
-void netif_create(netif_be_create_t *create);
-void netif_destroy(netif_be_destroy_t *destroy);
-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);
-#define netif_get(_b) (atomic_inc(&(_b)->refcnt))
-#define netif_put(_b) \
- do { \
- if ( atomic_dec_and_test(&(_b)->refcnt) ) \
- __netif_disconnect_complete(_b); \
- } while (0)
-
-void netif_interface_init(void);
-void netif_ctrlif_init(void);
-
-void netif_deschedule(netif_t *netif);
-
-int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev);
-struct net_device_stats *netif_be_get_stats(struct net_device *dev);
-void netif_be_int(int irq, void *dev_id, struct pt_regs *regs);
-
-#endif /* __NETIF__BACKEND__COMMON_H__ */
diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/control.c b/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/control.c
deleted file mode 100644
index cf1b075031..0000000000
--- a/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/control.c
+++ /dev/null
@@ -1,65 +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)
-{
- switch ( msg->subtype )
- {
- case CMSG_NETIF_BE_CREATE:
- if ( msg->length != sizeof(netif_be_create_t) )
- goto parse_error;
- netif_create((netif_be_create_t *)&msg->msg[0]);
- break;
- case CMSG_NETIF_BE_DESTROY:
- if ( msg->length != sizeof(netif_be_destroy_t) )
- goto parse_error;
- netif_destroy((netif_be_destroy_t *)&msg->msg[0]);
- break;
- case CMSG_NETIF_BE_CONNECT:
- if ( msg->length != sizeof(netif_be_connect_t) )
- goto parse_error;
- netif_connect((netif_be_connect_t *)&msg->msg[0]);
- break;
- case CMSG_NETIF_BE_DISCONNECT:
- if ( msg->length != sizeof(netif_be_disconnect_t) )
- goto parse_error;
- if ( !netif_disconnect((netif_be_disconnect_t *)&msg->msg[0],msg->id) )
- return; /* Sending the response is deferred until later. */
- break;
- default:
- goto parse_error;
- }
-
- ctrl_if_send_response(msg);
- return;
-
- parse_error:
- DPRINTK("Parse error while reading message subtype %d, len %d\n",
- msg->subtype, msg->length);
- msg->length = 0;
- ctrl_if_send_response(msg);
-}
-
-void netif_ctrlif_init(void)
-{
- ctrl_msg_t cmsg;
- netif_be_driver_status_changed_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_CHANGED;
- cmsg.length = sizeof(netif_be_driver_status_changed_t);
- st.status = NETIF_DRIVER_STATUS_UP;
- memcpy(cmsg.msg, &st, sizeof(st));
- ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-}
diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/interface.c b/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/interface.c
deleted file mode 100644
index 757d10ba2c..0000000000
--- a/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/interface.c
+++ /dev/null
@@ -1,282 +0,0 @@
-/******************************************************************************
- * arch/xen/drivers/netif/backend/interface.c
- *
- * Network-device interface management.
- *
- * Copyright (c) 2004, Keir Fraser
- */
-
-#include "common.h"
-#include <linux/rtnetlink.h>
-
-#define NETIF_HASHSZ 1024
-#define NETIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(NETIF_HASHSZ-1))
-
-static netif_t *netif_hash[NETIF_HASHSZ];
-
-netif_t *netif_find_by_handle(domid_t domid, unsigned int handle)
-{
- netif_t *netif = netif_hash[NETIF_HASH(domid, handle)];
- while ( (netif != NULL) &&
- ((netif->domid != domid) || (netif->handle != handle)) )
- netif = netif->hash_next;
- return netif;
-}
-
-void __netif_disconnect_complete(netif_t *netif)
-{
- ctrl_msg_t cmsg;
- netif_be_disconnect_t disc;
-
- /*
- * These can't be done in __netif_disconnect() because at that point there
- * may be outstanding requests at the disc whose asynchronous responses
- * must still be notified to the remote driver.
- */
- unbind_evtchn_from_irq(netif->evtchn);
- vfree(netif->tx); /* Frees netif->rx as well. */
- rtnl_lock();
- (void)dev_close(netif->dev);
- rtnl_unlock();
-
- /* 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_create(netif_be_create_t *create)
-{
- int err = 0;
- domid_t domid = create->domid;
- unsigned int handle = create->netif_handle;
- struct net_device *dev;
- 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;
- }
-
- netif = dev->priv;
- memset(netif, 0, sizeof(*netif));
- netif->domid = domid;
- netif->handle = handle;
- netif->status = DISCONNECTED;
- spin_lock_init(&netif->rx_lock);
- spin_lock_init(&netif->tx_lock);
- atomic_set(&netif->refcnt, 0);
- netif->dev = dev;
-
- netif->credit_bytes = netif->remaining_credit = ~0UL;
- netif->credit_usec = 0UL;
- /*init_ac_timer(&new_vif->credit_timeout);*/
-
- pnetif = &netif_hash[NETIF_HASH(domid, handle)];
- while ( *pnetif != NULL )
- {
- if ( ((*pnetif)->domid == domid) && ((*pnetif)->handle == handle) )
- {
- DPRINTK("Could not create netif: already exists\n");
- create->status = NETIF_BE_STATUS_INTERFACE_EXISTS;
- kfree(dev);
- return;
- }
- pnetif = &(*pnetif)->hash_next;
- }
-
- dev->hard_start_xmit = netif_be_start_xmit;
- dev->get_stats = netif_be_get_stats;
- memcpy(dev->dev_addr, create->mac, ETH_ALEN);
-
- /* Disable queuing. */
- dev->tx_queue_len = 0;
-
- /* Force a different MAC from remote end. */
- dev->dev_addr[2] ^= 1;
-
- if ( (err = register_netdev(dev)) != 0 )
- {
- DPRINTK("Could not register new net device %s: err=%d\n",
- dev->name, err);
- create->status = NETIF_BE_STATUS_OUT_OF_MEMORY;
- kfree(dev);
- return;
- }
-
- netif->hash_next = *pnetif;
- *pnetif = netif;
-
- DPRINTK("Successfully created netif\n");
- create->status = NETIF_BE_STATUS_OKAY;
-}
-
-void netif_destroy(netif_be_destroy_t *destroy)
-{
- domid_t domid = destroy->domid;
- unsigned int handle = destroy->netif_handle;
- netif_t **pnetif, *netif;
-
- pnetif = &netif_hash[NETIF_HASH(domid, handle)];
- while ( (netif = *pnetif) != NULL )
- {
- if ( (netif->domid == domid) && (netif->handle == handle) )
- {
- if ( netif->status != DISCONNECTED )
- goto still_connected;
- goto destroy;
- }
- pnetif = &netif->hash_next;
- }
-
- destroy->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND;
- return;
-
- still_connected:
- destroy->status = NETIF_BE_STATUS_INTERFACE_CONNECTED;
- return;
-
- destroy:
- *pnetif = netif->hash_next;
- unregister_netdev(netif->dev);
- kfree(netif->dev);
- destroy->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;
- pgprot_t prot;
- int error;
- netif_t *netif;
- struct net_device *eth0_dev;
-
- 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;
- }
-
- prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED);
- error = direct_remap_area_pages(&init_mm,
- VMALLOC_VMADDR(vma->addr),
- tx_shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
- prot, domid);
- 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;
- }
-
- netif->evtchn = evtchn;
- netif->irq = bind_evtchn_to_irq(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->status = CONNECTED;
- netif_get(netif);
-
- rtnl_lock();
- (void)dev_open(netif->dev);
- rtnl_unlock();
-
- (void)request_irq(netif->irq, netif_be_int, 0, netif->dev->name, netif);
- netif_start_queue(netif->dev);
-
- connect->status = NETIF_BE_STATUS_OKAY;
-}
-
-int netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id)
-{
- domid_t domid = disconnect->domid;
- unsigned int handle = disconnect->netif_handle;
- netif_t *netif;
-
- netif = netif_find_by_handle(domid, handle);
- if ( unlikely(netif == NULL) )
- {
- DPRINTK("netif_disconnect attempted for non-existent netif"
- " (%u,%u)\n", disconnect->domid, disconnect->netif_handle);
- disconnect->status = NETIF_BE_STATUS_INTERFACE_NOT_FOUND;
- return 1; /* Caller will send response error message. */
- }
-
- if ( netif->status == CONNECTED )
- {
- netif->status = DISCONNECTING;
- netif->disconnect_rspid = rsp_id;
- wmb(); /* Let other CPUs see the status change. */
- netif_stop_queue(netif->dev);
- free_irq(netif->irq, netif);
- netif_deschedule(netif);
- netif_put(netif);
- return 0; /* Caller should not send response message. */
- }
-
- disconnect->status = NETIF_BE_STATUS_OKAY;
- return 1;
-}
-
-void netif_interface_init(void)
-{
- memset(netif_hash, 0, sizeof(netif_hash));
-}
diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/main.c b/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/main.c
deleted file mode 100644
index 4dd55168a2..0000000000
--- a/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/main.c
+++ /dev/null
@@ -1,775 +0,0 @@
-/******************************************************************************
- * arch/xen/drivers/netif/backend/main.c
- *
- * Back-end of the driver for virtual block devices. This portion of the
- * driver exports a 'unified' block-device interface that can be accessed
- * by any operating system that implements a compatible front end. A
- * reference front-end implementation can be found in:
- * arch/xen/drivers/netif/frontend
- *
- * Copyright (c) 2002-2004, K A Fraser
- */
-
-#include "common.h"
-
-static void netif_page_release(struct page *page);
-static void make_tx_response(netif_t *netif,
- u16 id,
- s8 st);
-static int make_rx_response(netif_t *netif,
- u16 id,
- s8 st,
- memory_t addr,
- u16 size);
-
-static void net_tx_action(unsigned long unused);
-static DECLARE_TASKLET(net_tx_tasklet, net_tx_action, 0);
-
-static void net_rx_action(unsigned long unused);
-static DECLARE_TASKLET(net_rx_tasklet, net_rx_action, 0);
-
-static struct sk_buff_head rx_queue;
-static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE*2];
-static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE*3];
-static unsigned char rx_notify[NR_EVENT_CHANNELS];
-
-/* Don't currently gate addition of an interface to the tx scheduling list. */
-#define tx_work_exists(_if) (1)
-
-#define MAX_PENDING_REQS 256
-static unsigned long mmap_vstart;
-#define MMAP_VADDR(_req) (mmap_vstart + ((_req) * PAGE_SIZE))
-
-#define PKT_PROT_LEN (ETH_HLEN + 20)
-
-static struct {
- netif_tx_request_t req;
- netif_t *netif;
-} pending_tx_info[MAX_PENDING_REQS];
-static u16 pending_ring[MAX_PENDING_REQS];
-typedef unsigned int PEND_RING_IDX;
-#define MASK_PEND_IDX(_i) ((_i)&(MAX_PENDING_REQS-1))
-static PEND_RING_IDX pending_prod, pending_cons;
-#define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons)
-
-/* Freed TX SKBs get batched on this ring before return to pending_ring. */
-static u16 dealloc_ring[MAX_PENDING_REQS];
-static spinlock_t dealloc_lock = SPIN_LOCK_UNLOCKED;
-static PEND_RING_IDX dealloc_prod, dealloc_cons;
-
-static struct sk_buff_head tx_queue;
-static multicall_entry_t tx_mcl[MAX_PENDING_REQS];
-
-static struct list_head net_schedule_list;
-static spinlock_t net_schedule_list_lock;
-
-#define MAX_MFN_ALLOC 64
-static unsigned long mfn_list[MAX_MFN_ALLOC];
-static unsigned int alloc_index = 0;
-static spinlock_t mfn_lock = SPIN_LOCK_UNLOCKED;
-
-static void __refresh_mfn_list(void)
-{
- int ret = HYPERVISOR_dom_mem_op(MEMOP_increase_reservation,
- mfn_list, MAX_MFN_ALLOC);
- if ( unlikely(ret != MAX_MFN_ALLOC) )
- BUG();
- alloc_index = MAX_MFN_ALLOC;
-}
-
-static unsigned long get_new_mfn(void)
-{
- unsigned long mfn, flags;
- spin_lock_irqsave(&mfn_lock, flags);
- if ( alloc_index == 0 )
- __refresh_mfn_list();
- mfn = mfn_list[--alloc_index];
- spin_unlock_irqrestore(&mfn_lock, flags);
- return mfn;
-}
-
-static void dealloc_mfn(unsigned long mfn)
-{
- unsigned long flags;
- spin_lock_irqsave(&mfn_lock, flags);
- if ( alloc_index != MAX_MFN_ALLOC )
- mfn_list[alloc_index++] = mfn;
- else if ( HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, &mfn, 1) != 1 )
- BUG();
- spin_unlock_irqrestore(&mfn_lock, flags);
-}
-
-static inline void maybe_schedule_tx_action(void)
-{
- smp_mb();
- if ( (NR_PENDING_REQS < (MAX_PENDING_REQS/2)) &&
- !list_empty(&net_schedule_list) )
- tasklet_schedule(&net_tx_tasklet);
-}
-
-/*
- * This is the primary RECEIVE function for a network interface.
- * Note that, from the p.o.v. of /this/ OS it looks like a transmit.
- */
-int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- netif_t *netif = (netif_t *)dev->priv;
-
- ASSERT(skb->dev == dev);
-
- /* Drop the packet if the target domain has no receive buffers. */
- if ( (netif->rx_req_cons == netif->rx->req_prod) ||
- ((netif->rx_req_cons-netif->rx_resp_prod) == NETIF_RX_RING_SIZE) )
- goto drop;
-
- /*
- * We do not copy the packet unless:
- * 1. The data is shared; or
- * 2. It spans a page boundary; or
- * 3. We cannot be sure the whole data page is allocated.
- * The copying method is taken from skb_copy().
- * NB. We also couldn't cope with fragmented packets, but we won't get
- * any because we not advertise the NETIF_F_SG feature.
- */
- if ( skb_shared(skb) || skb_cloned(skb) ||
- (((unsigned long)skb->end ^ (unsigned long)skb->head) & PAGE_MASK) ||
- ((skb->end - skb->head) < (PAGE_SIZE/2)) )
- {
- struct sk_buff *nskb = alloc_skb(PAGE_SIZE-1024, GFP_ATOMIC);
- int hlen = skb->data - skb->head;
- if ( unlikely(nskb == NULL) )
- goto drop;
- skb_reserve(nskb, hlen);
- __skb_put(nskb, skb->len);
- (void)skb_copy_bits(skb, -hlen, nskb->head, hlen + skb->len);
- nskb->dev = skb->dev;
- dev_kfree_skb(skb);
- skb = nskb;
- }
-
- netif->rx_req_cons++;
-
- skb_queue_tail(&rx_queue, skb);
- tasklet_schedule(&net_rx_tasklet);
-
- return 0;
-
- drop:
- netif->stats.rx_dropped++;
- dev_kfree_skb(skb);
- return 0;
-}
-
-#if 0
-static void xen_network_done_notify(void)
-{
- static struct net_device *eth0_dev = NULL;
- if ( unlikely(eth0_dev == NULL) )
- eth0_dev = __dev_get_by_name("eth0");
- netif_rx_schedule(eth0_dev);
-}
-/*
- * Add following to poll() function in NAPI driver (Tigon3 is example):
- * if ( xen_network_done() )
- * tg3_enable_ints(tp);
- */
-int xen_network_done(void)
-{
- return skb_queue_empty(&rx_queue);
-}
-#endif
-
-static void net_rx_action(unsigned long unused)
-{
- netif_t *netif;
- s8 status;
- u16 size, id, evtchn;
- mmu_update_t *mmu;
- multicall_entry_t *mcl;
- unsigned long vdata, mdata, new_mfn;
- struct sk_buff_head rxq;
- struct sk_buff *skb;
- u16 notify_list[NETIF_RX_RING_SIZE];
- int notify_nr = 0;
-
- skb_queue_head_init(&rxq);
-
- mcl = rx_mcl;
- mmu = rx_mmu;
- while ( (skb = skb_dequeue(&rx_queue)) != NULL )
- {
- netif = (netif_t *)skb->dev->priv;
- vdata = (unsigned long)skb->data;
- mdata = virt_to_machine(vdata);
- new_mfn = get_new_mfn();
-
- mmu[0].ptr = (new_mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
- mmu[0].val = __pa(vdata) >> PAGE_SHIFT;
- mmu[1].val = (unsigned long)(netif->domid<<16) & ~0xFFFFUL;
- mmu[1].ptr = (unsigned long)(netif->domid<< 0) & ~0xFFFFUL;
- mmu[1].ptr |= MMU_EXTENDED_COMMAND;
- mmu[1].val |= MMUEXT_SET_SUBJECTDOM;
- mmu[2].ptr = (mdata & PAGE_MASK) | MMU_EXTENDED_COMMAND;
- mmu[2].val = MMUEXT_REASSIGN_PAGE;
-
- mcl[0].op = __HYPERVISOR_update_va_mapping;
- mcl[0].args[0] = vdata >> PAGE_SHIFT;
- mcl[0].args[1] = (new_mfn << PAGE_SHIFT) | __PAGE_KERNEL;
- mcl[0].args[2] = 0;
- mcl[1].op = __HYPERVISOR_mmu_update;
- mcl[1].args[0] = (unsigned long)mmu;
- mcl[1].args[1] = 3;
- mcl[1].args[2] = 0;
-
- mcl += 2;
- mmu += 3;
-
- __skb_queue_tail(&rxq, skb);
-
- /* Filled the batch queue? */
- if ( (mcl - rx_mcl) == ARRAY_SIZE(rx_mcl) )
- break;
- }
-
- if ( mcl == rx_mcl )
- return;
-
- mcl[-2].args[2] = UVMF_FLUSH_TLB;
- if ( unlikely(HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl) != 0) )
- BUG();
-
- mcl = rx_mcl;
- mmu = rx_mmu;
- while ( (skb = __skb_dequeue(&rxq)) != NULL )
- {
- netif = (netif_t *)skb->dev->priv;
- size = skb->tail - skb->data;
-
- /* Rederive the machine addresses. */
- new_mfn = mcl[0].args[1] >> PAGE_SHIFT;
- mdata = ((mmu[2].ptr & PAGE_MASK) |
- ((unsigned long)skb->data & ~PAGE_MASK));
-
- phys_to_machine_mapping[__pa(skb->data) >> PAGE_SHIFT] = new_mfn;
-
- atomic_set(&(skb_shinfo(skb)->dataref), 1);
- skb_shinfo(skb)->nr_frags = 0;
- skb_shinfo(skb)->frag_list = NULL;
-
- netif->stats.rx_bytes += size;
- netif->stats.rx_packets++;
-
- /* The update_va_mapping() must not fail. */
- if ( unlikely(mcl[0].args[5] != 0) )
- BUG();
-
- /* Check the reassignment error code. */
- status = NETIF_RSP_OKAY;
- if ( unlikely(mcl[1].args[5] != 0) )
- {
- DPRINTK("Failed MMU update transferring to DOM%u\n", netif->domid);
- dealloc_mfn(mdata >> PAGE_SHIFT);
- status = NETIF_RSP_ERROR;
- }
-
- evtchn = netif->evtchn;
- id = netif->rx->ring[MASK_NETIF_RX_IDX(netif->rx_resp_prod)].req.id;
- if ( make_rx_response(netif, id, status, mdata, size) &&
- (rx_notify[evtchn] == 0) )
- {
- rx_notify[evtchn] = 1;
- notify_list[notify_nr++] = evtchn;
- }
-
- dev_kfree_skb(skb);
-
- mcl += 2;
- mmu += 3;
- }
-
- while ( notify_nr != 0 )
- {
- evtchn = notify_list[--notify_nr];
- rx_notify[evtchn] = 0;
- notify_via_evtchn(evtchn);
- }
-
- /* More work to do? */
- if ( !skb_queue_empty(&rx_queue) )
- tasklet_schedule(&net_rx_tasklet);
-#if 0
- else
- xen_network_done_notify();
-#endif
-}
-
-struct net_device_stats *netif_be_get_stats(struct net_device *dev)
-{
- netif_t *netif = dev->priv;
- return &netif->stats;
-}
-
-static int __on_net_schedule_list(netif_t *netif)
-{
- return netif->list.next != NULL;
-}
-
-static void remove_from_net_schedule_list(netif_t *netif)
-{
- spin_lock_irq(&net_schedule_list_lock);
- if ( likely(__on_net_schedule_list(netif)) )
- {
- list_del(&netif->list);
- netif->list.next = NULL;
- netif_put(netif);
- }
- spin_unlock_irq(&net_schedule_list_lock);
-}
-
-static void add_to_net_schedule_list_tail(netif_t *netif)
-{
- if ( __on_net_schedule_list(netif) )
- return;
-
- spin_lock_irq(&net_schedule_list_lock);
- if ( !__on_net_schedule_list(netif) && (netif->status == CONNECTED) )
- {
- list_add_tail(&netif->list, &net_schedule_list);
- netif_get(netif);
- }
- spin_unlock_irq(&net_schedule_list_lock);
-}
-
-static inline void netif_schedule_work(netif_t *netif)
-{
- if ( (netif->tx_req_cons != netif->tx->req_prod) &&
- ((netif->tx_req_cons-netif->tx_resp_prod) != NETIF_TX_RING_SIZE) )
- {
- add_to_net_schedule_list_tail(netif);
- maybe_schedule_tx_action();
- }
-}
-
-void netif_deschedule(netif_t *netif)
-{
- remove_from_net_schedule_list(netif);
-}
-
-#if 0
-static void tx_credit_callback(unsigned long data)
-{
- netif_t *netif = (netif_t *)data;
- netif->remaining_credit = netif->credit_bytes;
- netif_schedule_work(netif);
-}
-#endif
-
-static void net_tx_action(unsigned long unused)
-{
- struct list_head *ent;
- struct sk_buff *skb;
- netif_t *netif;
- netif_tx_request_t txreq;
- u16 pending_idx;
- NETIF_RING_IDX i;
- struct page *page;
- multicall_entry_t *mcl;
- PEND_RING_IDX dc, dp;
-
- if ( (dc = dealloc_cons) == (dp = dealloc_prod) )
- goto skip_dealloc;
-
- mcl = tx_mcl;
- while ( dc != dp )
- {
- pending_idx = dealloc_ring[MASK_PEND_IDX(dc++)];
- mcl[0].op = __HYPERVISOR_update_va_mapping;
- mcl[0].args[0] = MMAP_VADDR(pending_idx) >> PAGE_SHIFT;
- mcl[0].args[1] = 0;
- mcl[0].args[2] = 0;
- mcl++;
- }
-
- mcl[-1].args[2] = UVMF_FLUSH_TLB;
- if ( unlikely(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0) )
- BUG();
-
- mcl = tx_mcl;
- while ( dealloc_cons != dp )
- {
- /* The update_va_mapping() must not fail. */
- if ( unlikely(mcl[0].args[5] != 0) )
- BUG();
-
- pending_idx = dealloc_ring[MASK_PEND_IDX(dealloc_cons++)];
-
- netif = pending_tx_info[pending_idx].netif;
-
- spin_lock(&netif->tx_lock);
- make_tx_response(netif, pending_tx_info[pending_idx].req.id,
- NETIF_RSP_OKAY);
- spin_unlock(&netif->tx_lock);
-
- pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
-
- /*
- * Scheduling checks must happen after the above response is posted.
- * This avoids a possible race with a guest OS on another CPU.
- */
- mb();
- if ( (netif->tx_req_cons != netif->tx->req_prod) &&
- ((netif->tx_req_cons-netif->tx_resp_prod) != NETIF_TX_RING_SIZE) )
- add_to_net_schedule_list_tail(netif);
-
- netif_put(netif);
-
- mcl++;
- }
-
- skip_dealloc:
- mcl = tx_mcl;
- while ( (NR_PENDING_REQS < MAX_PENDING_REQS) &&
- !list_empty(&net_schedule_list) )
- {
- /* Get a netif from the list with work to do. */
- ent = net_schedule_list.next;
- netif = list_entry(ent, netif_t, list);
- netif_get(netif);
- remove_from_net_schedule_list(netif);
-
- /* Work to do? */
- i = netif->tx_req_cons;
- if ( (i == netif->tx->req_prod) ||
- ((i-netif->tx_resp_prod) == NETIF_TX_RING_SIZE) )
- {
- netif_put(netif);
- continue;
- }
- memcpy(&txreq, &netif->tx->ring[MASK_NETIF_TX_IDX(i)].req,
- sizeof(txreq));
- netif->tx_req_cons++;
-
-#if 0
- /* Credit-based scheduling. */
- if ( tx.size > netif->remaining_credit )
- {
- s_time_t now = NOW(), next_credit =
- netif->credit_timeout.expires + MICROSECS(netif->credit_usec);
- if ( next_credit <= now )
- {
- netif->credit_timeout.expires = now;
- netif->remaining_credit = netif->credit_bytes;
- }
- else
- {
- netif->remaining_credit = 0;
- netif->credit_timeout.expires = next_credit;
- netif->credit_timeout.data = (unsigned long)netif;
- netif->credit_timeout.function = tx_credit_callback;
- netif->credit_timeout.cpu = smp_processor_id();
- add_ac_timer(&netif->credit_timeout);
- break;
- }
- }
- netif->remaining_credit -= tx.size;
-#endif
-
- netif_schedule_work(netif);
-
- if ( unlikely(txreq.size <= PKT_PROT_LEN) ||
- unlikely(txreq.size > ETH_FRAME_LEN) )
- {
- DPRINTK("Bad packet size: %d\n", txreq.size);
- make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
- netif_put(netif);
- continue;
- }
-
- /* No crossing a page boundary as the payload mustn't fragment. */
- if ( unlikely(((txreq.addr & ~PAGE_MASK) + txreq.size) >= PAGE_SIZE) )
- {
- DPRINTK("txreq.addr: %lx, size: %u, end: %lu\n",
- txreq.addr, txreq.size,
- (txreq.addr &~PAGE_MASK) + txreq.size);
- make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
- netif_put(netif);
- continue;
- }
-
- pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
-
- if ( unlikely((skb = alloc_skb(PKT_PROT_LEN+16, GFP_ATOMIC)) == NULL) )
- {
- DPRINTK("Can't allocate a skb in start_xmit.\n");
- make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
- netif_put(netif);
- break;
- }
-
- /* Packets passed to netif_rx() must have some headroom. */
- skb_reserve(skb, 16);
-
- mcl[0].op = __HYPERVISOR_update_va_mapping_otherdomain;
- mcl[0].args[0] = MMAP_VADDR(pending_idx) >> PAGE_SHIFT;
- mcl[0].args[1] = (txreq.addr & PAGE_MASK) | __PAGE_KERNEL;
- mcl[0].args[2] = 0;
- mcl[0].args[3] = netif->domid;
- mcl++;
-
- memcpy(&pending_tx_info[pending_idx].req, &txreq, sizeof(txreq));
- pending_tx_info[pending_idx].netif = netif;
- *((u16 *)skb->data) = pending_idx;
-
- __skb_queue_tail(&tx_queue, skb);
-
- pending_cons++;
-
- /* Filled the batch queue? */
- if ( (mcl - tx_mcl) == ARRAY_SIZE(tx_mcl) )
- break;
- }
-
- if ( mcl == tx_mcl )
- return;
-
- if ( unlikely(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0) )
- BUG();
-
- mcl = tx_mcl;
- while ( (skb = __skb_dequeue(&tx_queue)) != NULL )
- {
- pending_idx = *((u16 *)skb->data);
- netif = pending_tx_info[pending_idx].netif;
- memcpy(&txreq, &pending_tx_info[pending_idx].req, sizeof(txreq));
-
- /* Check the remap error code. */
- if ( unlikely(mcl[0].args[5] != 0) )
- {
- DPRINTK("Bad page frame\n");
- make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
- netif_put(netif);
- kfree_skb(skb);
- mcl++;
- pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
- continue;
- }
-
- phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT] =
- txreq.addr >> PAGE_SHIFT;
-
- __skb_put(skb, PKT_PROT_LEN);
- memcpy(skb->data,
- (void *)(MMAP_VADDR(pending_idx)|(txreq.addr&~PAGE_MASK)),
- PKT_PROT_LEN);
-
- page = virt_to_page(MMAP_VADDR(pending_idx));
-
- /* Append the packet payload as a fragment. */
- skb_shinfo(skb)->frags[0].page = page;
- skb_shinfo(skb)->frags[0].size = txreq.size - PKT_PROT_LEN;
- skb_shinfo(skb)->frags[0].page_offset =
- (txreq.addr + PKT_PROT_LEN) & ~PAGE_MASK;
- skb_shinfo(skb)->nr_frags = 1;
- skb->data_len = txreq.size - PKT_PROT_LEN;
- skb->len += skb->data_len;
-
- skb->dev = netif->dev;
- skb->protocol = eth_type_trans(skb, skb->dev);
-
- /*
- * Destructor information. We hideously abuse the 'mapping' pointer,
- * which isn't otherwise used by us. The page deallocator is modified
- * to interpret a non-NULL value as a destructor function to be called.
- * This works okay because in all other cases the pointer must be NULL
- * when the page is freed (normally Linux will explicitly bug out if
- * it sees otherwise.
- */
- page->mapping = (struct address_space *)netif_page_release;
- atomic_set(&page->count, 1);
-
- netif->stats.tx_bytes += txreq.size;
- netif->stats.tx_packets++;
-
- netif_rx(skb);
- netif->dev->last_rx = jiffies;
-
- mcl++;
- }
-}
-
-static void netif_page_release(struct page *page)
-{
- unsigned long flags;
- u16 pending_idx = page - virt_to_page(mmap_vstart);
-
- /* Stop the abuse. */
- page->mapping = NULL;
-
- spin_lock_irqsave(&dealloc_lock, flags);
- dealloc_ring[MASK_PEND_IDX(dealloc_prod++)] = pending_idx;
- spin_unlock_irqrestore(&dealloc_lock, flags);
-
- tasklet_schedule(&net_tx_tasklet);
-}
-
-#if 0
-long flush_bufs_for_netif(netif_t *netif)
-{
- NETIF_RING_IDX i;
-
- /* Return any outstanding receive buffers to the guest OS. */
- spin_lock(&netif->rx_lock);
- for ( i = netif->rx_req_cons;
- (i != netif->rx->req_prod) &&
- ((i-netif->rx_resp_prod) != NETIF_RX_RING_SIZE);
- i++ )
- {
- make_rx_response(netif,
- netif->rx->ring[MASK_NETIF_RX_IDX(i)].req.id,
- NETIF_RSP_DROPPED, 0, 0);
- }
- netif->rx_req_cons = i;
- spin_unlock(&netif->rx_lock);
-
- /*
- * Flush pending transmit buffers. The guest may still have to wait for
- * buffers that are queued at a physical NIC.
- */
- spin_lock(&netif->tx_lock);
- for ( i = netif->tx_req_cons;
- (i != netif->tx->req_prod) &&
- ((i-netif->tx_resp_prod) != NETIF_TX_RING_SIZE);
- i++ )
- {
- make_tx_response(netif,
- netif->tx->ring[MASK_NETIF_TX_IDX(i)].req.id,
- NETIF_RSP_DROPPED);
- }
- netif->tx_req_cons = i;
- spin_unlock(&netif->tx_lock);
-
- return 0;
-}
-#endif
-
-void netif_be_int(int irq, void *dev_id, struct pt_regs *regs)
-{
- netif_t *netif = dev_id;
- if ( tx_work_exists(netif) )
- {
- add_to_net_schedule_list_tail(netif);
- maybe_schedule_tx_action();
- }
-}
-
-static void make_tx_response(netif_t *netif,
- u16 id,
- s8 st)
-{
- NETIF_RING_IDX i = netif->tx_resp_prod;
- netif_tx_response_t *resp;
-
- resp = &netif->tx->ring[MASK_NETIF_TX_IDX(i)].resp;
- resp->id = id;
- resp->status = st;
- wmb();
- netif->tx->resp_prod = netif->tx_resp_prod = ++i;
-
- mb(); /* Update producer before checking event threshold. */
- if ( i == netif->tx->event )
- notify_via_evtchn(netif->evtchn);
-}
-
-static int make_rx_response(netif_t *netif,
- u16 id,
- s8 st,
- memory_t addr,
- u16 size)
-{
- NETIF_RING_IDX i = netif->rx_resp_prod;
- netif_rx_response_t *resp;
-
- resp = &netif->rx->ring[MASK_NETIF_RX_IDX(i)].resp;
- resp->addr = addr;
- resp->id = id;
- resp->status = (s16)size;
- if ( st < 0 )
- resp->status = (s16)st;
- wmb();
- netif->rx->resp_prod = netif->rx_resp_prod = ++i;
-
- mb(); /* Update producer before checking event threshold. */
- return (i == netif->rx->event);
-}
-
-static void netif_be_dbg(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct list_head *ent;
- netif_t *netif;
- int i = 0;
-
- printk(KERN_ALERT "netif_schedule_list:\n");
- spin_lock_irq(&net_schedule_list_lock);
-
- list_for_each ( ent, &net_schedule_list )
- {
- netif = list_entry(ent, netif_t, list);
- printk(KERN_ALERT " %d: private(rx_req_cons=%08x rx_resp_prod=%08x\n",
- i, netif->rx_req_cons, netif->rx_resp_prod);
- printk(KERN_ALERT " tx_req_cons=%08x tx_resp_prod=%08x)\n",
- netif->tx_req_cons, netif->tx_resp_prod);
- printk(KERN_ALERT " shared(rx_req_prod=%08x rx_resp_prod=%08x\n",
- netif->rx->req_prod, netif->rx->resp_prod);
- printk(KERN_ALERT " rx_event=%08x tx_req_prod=%08x\n",
- netif->rx->event, netif->tx->req_prod);
- printk(KERN_ALERT " tx_resp_prod=%08x, tx_event=%08x)\n",
- netif->tx->resp_prod, netif->tx->event);
- i++;
- }
-
- spin_unlock_irq(&net_schedule_list_lock);
- printk(KERN_ALERT " ** End of netif_schedule_list **\n");
-}
-
-static int __init init_module(void)
-{
- int i;
-
- if ( !(start_info.flags & SIF_NET_BE_DOMAIN) &&
- !(start_info.flags & SIF_INITDOMAIN) )
- return 0;
-
- printk("Initialising Xen netif backend\n");
-
- skb_queue_head_init(&rx_queue);
- skb_queue_head_init(&tx_queue);
-
- netif_interface_init();
-
- if ( (mmap_vstart = allocate_empty_lowmem_region(MAX_PENDING_REQS)) == 0 )
- BUG();
-
- pending_cons = 0;
- pending_prod = MAX_PENDING_REQS;
- for ( i = 0; i < MAX_PENDING_REQS; i++ )
- pending_ring[i] = i;
-
- spin_lock_init(&net_schedule_list_lock);
- INIT_LIST_HEAD(&net_schedule_list);
-
- netif_ctrlif_init();
-
- (void)request_irq(bind_virq_to_irq(VIRQ_DEBUG),
- netif_be_dbg, SA_SHIRQ,
- "net-be-dbg", &netif_be_dbg);
-
- return 0;
-}
-
-static void cleanup_module(void)
-{
- BUG();
-}
-
-module_init(init_module);
-module_exit(cleanup_module);
diff --git a/linux-2.4.26-xen-sparse/mkbuildtree b/linux-2.4.26-xen-sparse/mkbuildtree
index 46b992a988..16465f2fca 100755
--- a/linux-2.4.26-xen-sparse/mkbuildtree
+++ b/linux-2.4.26-xen-sparse/mkbuildtree
@@ -239,3 +239,9 @@ ln -sf ../../../../${LINUX_26}/drivers/xen/privcmd/privcmd.c core.c
cd ${AD}/arch/xen/drivers/netif/frontend
ln -sf ../../../../../${LINUX_26}/drivers/xen/netfront/netfront.c main.c
+
+cd ${AD}/arch/xen/drivers/netif/backend
+ln -sf ../../../../../${LINUX_26}/drivers/xen/netback/common.h
+ln -sf ../../../../../${LINUX_26}/drivers/xen/netback/control.c
+ln -sf ../../../../../${LINUX_26}/drivers/xen/netback/interface.c
+ln -sf ../../../../../${LINUX_26}/drivers/xen/netback/netback.c main.c