diff options
author | cl349@freefall.cl.cam.ac.uk <cl349@freefall.cl.cam.ac.uk> | 2004-07-31 16:13:15 +0000 |
---|---|---|
committer | cl349@freefall.cl.cam.ac.uk <cl349@freefall.cl.cam.ac.uk> | 2004-07-31 16:13:15 +0000 |
commit | 18f29ff781a8961e61a80abfe460c335401a4ab6 (patch) | |
tree | e6c30950674d6e7ca9b6510db6106827f4825ef5 /linux-2.4.26-xen-sparse | |
parent | ff2b591309e31b2f3fa275e9da79d55e0414719d (diff) | |
download | xen-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')
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 |