diff options
author | akw27@boulderdash.cl.cam.ac.uk <akw27@boulderdash.cl.cam.ac.uk> | 2003-02-14 14:27:45 +0000 |
---|---|---|
committer | akw27@boulderdash.cl.cam.ac.uk <akw27@boulderdash.cl.cam.ac.uk> | 2003-02-14 14:27:45 +0000 |
commit | ed220108094cf8e5c3f70a7421182cdbcb59f3d3 (patch) | |
tree | 22722275b0a231a057b08d99825b24d551545396 /xenolinux-2.4.16-sparse/arch | |
parent | ce62d9e7f6d76422b025939279a2a51b5262a06d (diff) | |
parent | 77cf55f0b8964f4d82d7119bfe59db8fddf4b320 (diff) | |
download | xen-ed220108094cf8e5c3f70a7421182cdbcb59f3d3.tar.gz xen-ed220108094cf8e5c3f70a7421182cdbcb59f3d3.tar.bz2 xen-ed220108094cf8e5c3f70a7421182cdbcb59f3d3.zip |
bitkeeper revision 1.34 (3e4cfce1Ot4YJzJ4jwNjDthlFrZV5w)
conflict resolution.
Diffstat (limited to 'xenolinux-2.4.16-sparse/arch')
-rw-r--r-- | xenolinux-2.4.16-sparse/arch/xeno/drivers/network/network.c | 127 |
1 files changed, 101 insertions, 26 deletions
diff --git a/xenolinux-2.4.16-sparse/arch/xeno/drivers/network/network.c b/xenolinux-2.4.16-sparse/arch/xeno/drivers/network/network.c index b018e29e49..87b1a97fdc 100644 --- a/xenolinux-2.4.16-sparse/arch/xeno/drivers/network/network.c +++ b/xenolinux-2.4.16-sparse/arch/xeno/drivers/network/network.c @@ -21,14 +21,12 @@ #include <linux/skbuff.h> #include <linux/init.h> +#include <asm/io.h> #include <net/sock.h> #define NET_TX_IRQ _EVENT_NET_TX #define NET_RX_IRQ _EVENT_NET_RX -#define NET_TX_IRQ_FOR_VIF(x) _EVENT_NET_TX_FOR_VIF(x) -#define NET_RX_IRQ_FOR_VIF(x) _EVENT_NET_RX_FOR_VIF(x) - #define TX_MAX_ENTRIES (TX_RING_SIZE - 2) #define RX_MAX_ENTRIES (RX_RING_SIZE - 2) @@ -37,7 +35,7 @@ #define TX_RING_ADD(_i,_j) (((_i)+(_j)) & (TX_RING_SIZE-1)) #define RX_RING_ADD(_i,_j) (((_i)+(_j)) & (RX_RING_SIZE-1)) -#define RX_BUF_SIZE 1600 /* Ethernet MTU + plenty of slack! */ +#define RX_BUF_SIZE 2049 /* (was 1600) Ethernet MTU + plenty of slack! */ static void network_rx_int(int irq, void *dev_id, struct pt_regs *ptregs); static void network_tx_int(int irq, void *dev_id, struct pt_regs *ptregs); @@ -48,6 +46,8 @@ static void cleanup_module(void); static struct list_head dev_list; +static unsigned int net_countx; + /* * RX RING: RX_IDX <= rx_cons <= rx_prod * TX RING: TX_IDX <= tx_cons <= tx_prod @@ -72,16 +72,8 @@ struct net_private static int network_open(struct net_device *dev) { struct net_private *np = dev->priv; - int error; - char *rxlabel, *txlabel; - - // This is inevitably not the right way to allocate a couple of static strings. - rxlabel = kmalloc(sizeof("net-rx- "), GFP_KERNEL); - txlabel = kmalloc(sizeof("net-tx- "), GFP_KERNEL); - if ((rxlabel == NULL) || (txlabel == NULL)) goto fail; - sprintf(rxlabel, "net-rx-%d", np->id); - sprintf(txlabel, "net-tx-%d", np->id); - + int error = 0; + np->rx_idx = np->tx_idx = np->tx_full = 0; memset(&np->stats, 0, sizeof(np->stats)); @@ -113,8 +105,8 @@ static int network_open(struct net_device *dev) network_alloc_rx_buffers(dev); - error = request_irq(NET_RX_IRQ_FOR_VIF(np->id), network_rx_int, 0, - rxlabel, dev); + error = request_irq(NET_RX_IRQ, network_rx_int, 0, + "net-rx", dev); if ( error ) { printk(KERN_WARNING "%s: Could not allocate receive interrupt\n", @@ -122,13 +114,13 @@ static int network_open(struct net_device *dev) goto fail; } - error = request_irq(NET_TX_IRQ_FOR_VIF(np->id), network_tx_int, 0, - txlabel, dev); + error = request_irq(NET_TX_IRQ, network_tx_int, 0, + "net-tx", dev); if ( error ) { printk(KERN_WARNING "%s: Could not allocate transmit interrupt\n", dev->name); - free_irq(NET_RX_IRQ_FOR_VIF(np->id), dev); + free_irq(NET_RX_IRQ, dev); goto fail; } @@ -141,8 +133,6 @@ static int network_open(struct net_device *dev) return 0; fail: - if ( rxlabel ) kfree(rxlabel); - if ( txlabel ) kfree(txlabel); if ( np->net_ring->rx_ring ) kfree(np->net_ring->rx_ring); if ( np->net_ring->tx_ring ) kfree(np->net_ring->tx_ring); if ( np->rx_skb_ring ) kfree(np->rx_skb_ring); @@ -179,13 +169,59 @@ static void network_tx_buf_gc(struct net_device *dev) spin_unlock_irqrestore(&np->tx_lock, flags); } +inline unsigned long get_ppte(unsigned long addr) +{ + unsigned long ppte = 0xdeadbeef; + pgd_t *pgd; pmd_t *pmd; pte_t *ptep; + pgd = pgd_offset_k(addr); + + if (pgd_none(*pgd) || pgd_bad(*pgd)) BUG(); + + pmd = pmd_offset(pgd, addr); + if (pmd_none(*pmd)) BUG(); + if (pmd_bad(*pmd)) BUG(); + + ptep = pte_offset(pmd, addr); + ppte = (unsigned long)phys_to_machine(virt_to_phys(ptep)); + + return ppte; +} +/* +static void validate_free_list(void) +{ + unsigned long addr, ppfn, mpfn, mpfn2, flags; + struct list_head *i; + struct net_page_info *np; + + printk(KERN_ALERT "Walking free pages:\n"); + + spin_lock_irqsave(&net_page_list_lock, flags); + + list_for_each(i, &net_page_list) + { + np = list_entry(i, struct net_page_info, list); + addr = np->virt_addr; + ppfn = virt_to_phys(addr) >> PAGE_SHIFT; + mpfn = get_ppte(addr); + mpfn2 = phys_to_machine_mapping[ppfn]; + + mpfn = (*(unsigned long *)phys_to_virt(machine_to_phys(mpfn))) >> PAGE_SHIFT; + if (mpfn != mpfn2) printk(KERN_ALERT "mpfn %lu != %lu\n", mpfn, mpfn2); + if (machine_to_phys_mapping[mpfn] != ppfn) printk(KERN_ALERT "ppfn %lu != %lu\n", machine_to_phys_mapping[mpfn], ppfn); + } + + spin_unlock_irqrestore(&net_page_list_lock, flags); + +} +*/ static void network_alloc_rx_buffers(struct net_device *dev) { unsigned int i; struct net_private *np = dev->priv; struct sk_buff *skb; unsigned int end = RX_RING_ADD(np->rx_idx, RX_MAX_ENTRIES); + for ( i = np->net_ring->rx_prod; i != end; i = RX_RING_INC(i) ) { @@ -194,8 +230,9 @@ static void network_alloc_rx_buffers(struct net_device *dev) skb->dev = dev; skb_reserve(skb, 2); /* word align the IP header */ np->rx_skb_ring[i] = skb; - np->net_ring->rx_ring[i].addr = (unsigned long)skb->data; + np->net_ring->rx_ring[i].addr = get_ppte(skb->head); np->net_ring->rx_ring[i].size = RX_BUF_SIZE - 16; /* arbitrary */ +//printk(KERN_ALERT "[%p]\n", phys_to_machine(virt_to_phys(skb->page_ptr))); } np->net_ring->rx_prod = i; @@ -219,6 +256,14 @@ static void network_free_rx_buffers(struct net_device *dev) } } +void print_range(u8 *start, unsigned int len) +{ + int i = 0; + + while (i++ < len) + printk("%x:", start[i]); + printk("\n"); +} static int network_start_xmit(struct sk_buff *skb, struct net_device *dev) { @@ -231,10 +276,23 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev) netif_stop_queue(dev); return -ENOBUFS; } - +//print_range(skb->data, ETH_HLEN + 8); +//print_range(skb->data + ETH_HLEN + 8, 20); +//printk("skb->len is %u in guestOS (expected fraglen: %u).\n", skb->len, skb->len - (ETH_HLEN + 8)); i = np->net_ring->tx_prod; + + if ( (((unsigned long)skb->data & ~PAGE_MASK) + skb->len) >= PAGE_SIZE ) + { + struct sk_buff *new_skb = alloc_skb(RX_BUF_SIZE, GFP_KERNEL); + skb_put(new_skb, skb->len); + memcpy(new_skb->data, skb->data, skb->len); + kfree_skb(skb); + skb = new_skb; + } + np->tx_skb_ring[i] = skb; - np->net_ring->tx_ring[i].addr = (unsigned long)skb->data; + np->net_ring->tx_ring[i].addr + = (unsigned long)phys_to_machine(virt_to_phys(skb->data)); np->net_ring->tx_ring[i].size = skb->len; np->net_ring->tx_prod = TX_RING_INC(i); atomic_inc(&np->tx_entries); @@ -273,13 +331,30 @@ static void network_rx_int(int irq, void *dev_id, struct pt_regs *ptregs) struct net_private *np = dev->priv; struct sk_buff *skb; + /*if (net_countx++ % 100 == 0) validate_free_list();*/ + again: for ( i = np->rx_idx; i != np->net_ring->rx_cons; i = RX_RING_INC(i) ) { + if (np->net_ring->rx_ring[i].status != RING_STATUS_OK) + { + printk("bad buffer on RX ring!(%d)\n", + np->net_ring->rx_ring[i].status); + continue; + } skb = np->rx_skb_ring[i]; + +//printk(KERN_ALERT "[%u]: ptmm[%lx] old:(%lx) new:(%lx)\n", i , virt_to_phys(skb->head) >> PAGE_SHIFT, phys_to_machine_mapping[virt_to_phys(skb->head) >> PAGE_SHIFT], (*(unsigned long *)phys_to_virt(machine_to_phys(np->net_ring->rx_ring[i].addr))) >> PAGE_SHIFT); + + phys_to_machine_mapping[virt_to_phys(skb->head) >> PAGE_SHIFT] = + (*(unsigned long *)phys_to_virt( + machine_to_phys(np->net_ring->rx_ring[i].addr)) + ) >> PAGE_SHIFT; + skb_put(skb, np->net_ring->rx_ring[i].size); skb->protocol = eth_type_trans(skb, dev); np->stats.rx_packets++; + np->stats.rx_bytes += np->net_ring->rx_ring[i].size; netif_rx(skb); dev->last_rx = jiffies; @@ -309,8 +384,8 @@ int network_close(struct net_device *dev) struct net_private *np = dev->priv; netif_stop_queue(dev); - free_irq(NET_RX_IRQ_FOR_VIF(np->id), dev); - free_irq(NET_TX_IRQ_FOR_VIF(np->id), dev); + free_irq(NET_RX_IRQ, dev); + free_irq(NET_TX_IRQ, dev); network_free_rx_buffers(dev); kfree(np->net_ring->rx_ring); kfree(np->net_ring->tx_ring); |