From 1f730cca160c8aa39bd7d6978cb326e4d8bc77f7 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 16 Sep 2005 10:57:31 +0000 Subject: [PATCH 1/4] direct_remap_pfn_range() takes a vm_area_struct rather than an mm_struct. Also it sets VM_RESERVED and VM_IO, just like generic remap_pfn_range() in mm/memory.c. Signed-off-by: Keir Fraser --- .../arch/xen/i386/mm/ioremap.c | 31 ++++++++++++++----- linux-2.6-xen-sparse/arch/xen/i386/pci/i386.c | 2 +- linux-2.6-xen-sparse/arch/xen/kernel/devmem.c | 16 ++-------- .../drivers/xen/privcmd/privcmd.c | 12 +++---- .../include/asm-xen/asm-i386/pgtable.h | 6 ++-- .../include/asm-xen/asm-x86_64/pgtable.h | 6 ++-- 6 files changed, 38 insertions(+), 35 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c b/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c index 8016210ece..dea309b13c 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c @@ -45,12 +45,12 @@ static int direct_remap_area_pte_fn(pte_t *pte, return 0; } -int direct_remap_pfn_range(struct mm_struct *mm, - unsigned long address, - unsigned long mfn, - unsigned long size, - pgprot_t prot, - domid_t domid) +static int __direct_remap_pfn_range(struct mm_struct *mm, + unsigned long address, + unsigned long mfn, + unsigned long size, + pgprot_t prot, + domid_t domid) { int i; unsigned long start_address; @@ -98,6 +98,20 @@ int direct_remap_pfn_range(struct mm_struct *mm, return 0; } +int direct_remap_pfn_range(struct vm_area_struct *vma, + unsigned long address, + unsigned long mfn, + unsigned long size, + pgprot_t prot, + domid_t domid) +{ + /* Same as remap_pfn_range(). */ + vma->vm_flags |= VM_IO | VM_RESERVED; + + return __direct_remap_pfn_range( + vma->vm_mm, address, mfn, size, prot, domid); +} + EXPORT_SYMBOL(direct_remap_pfn_range); @@ -221,8 +235,9 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l #ifdef __x86_64__ flags |= _PAGE_USER; #endif - if (direct_remap_pfn_range(&init_mm, (unsigned long) addr, phys_addr>>PAGE_SHIFT, - size, __pgprot(flags), domid)) { + if (__direct_remap_pfn_range(&init_mm, (unsigned long)addr, + phys_addr>>PAGE_SHIFT, + size, __pgprot(flags), domid)) { vunmap((void __force *) addr); return NULL; } diff --git a/linux-2.6-xen-sparse/arch/xen/i386/pci/i386.c b/linux-2.6-xen-sparse/arch/xen/i386/pci/i386.c index e132e7d42d..aa6e1aa7ea 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/pci/i386.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/pci/i386.c @@ -295,7 +295,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, /* Write-combine setting is ignored, it is changed via the mtrr * interfaces on this platform. */ - if (direct_remap_pfn_range(vma->vm_mm, vma->vm_start, vma->vm_pgoff, + if (direct_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, vma->vm_end - vma->vm_start, vma->vm_page_prot, DOMID_IO)) return -EAGAIN; diff --git a/linux-2.6-xen-sparse/arch/xen/kernel/devmem.c b/linux-2.6-xen-sparse/arch/xen/kernel/devmem.c index 3b713f6375..d7093bbeb6 100644 --- a/linux-2.6-xen-sparse/arch/xen/kernel/devmem.c +++ b/linux-2.6-xen-sparse/arch/xen/kernel/devmem.c @@ -90,22 +90,10 @@ out: static int mmap_mem(struct file * file, struct vm_area_struct * vma) { - int uncached; - - uncached = uncached_access(file); - if (uncached) + if (uncached_access(file)) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - /* Don't try to swap out physical pages.. */ - vma->vm_flags |= VM_RESERVED; - - /* - * Don't dump addresses that are not real memory to a core file. - */ - if (uncached) - vma->vm_flags |= VM_IO; - - if (direct_remap_pfn_range(vma->vm_mm, vma->vm_start, vma->vm_pgoff, + if (direct_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, vma->vm_end - vma->vm_start, vma->vm_page_prot, DOMID_IO)) return -EAGAIN; diff --git a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c index d12a86347f..9a21ec8d4e 100644 --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c @@ -130,12 +130,12 @@ static int privcmd_ioctl(struct inode *inode, struct file *file, if ( (msg[j].va + (msg[j].npages< vma->vm_end ) return -EINVAL; - if ( (rc = direct_remap_pfn_range(vma->vm_mm, - msg[j].va&PAGE_MASK, - msg[j].mfn, - msg[j].npages<vm_page_prot, - mmapcmd.dom)) < 0 ) + if ( (rc = direct_remap_pfn_range(vma, + msg[j].va&PAGE_MASK, + msg[j].mfn, + msg[j].npages<vm_page_prot, + mmapcmd.dom)) < 0 ) return rc; } } diff --git a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h index 1db7c0382e..6deb1d8eb8 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h @@ -460,7 +460,7 @@ void make_pages_writable(void *va, unsigned int nr); #define kern_addr_valid(addr) (1) #endif /* !CONFIG_DISCONTIGMEM */ -int direct_remap_pfn_range(struct mm_struct *mm, +int direct_remap_pfn_range(struct vm_area_struct *vma, unsigned long address, unsigned long mfn, unsigned long size, @@ -474,10 +474,10 @@ int touch_pte_range(struct mm_struct *mm, unsigned long size); #define io_remap_page_range(vma,from,phys,size,prot) \ -direct_remap_pfn_range(vma->vm_mm,from,phys>>PAGE_SHIFT,size,prot,DOMID_IO) +direct_remap_pfn_range(vma,from,(phys)>>PAGE_SHIFT,size,prot,DOMID_IO) #define io_remap_pfn_range(vma,from,pfn,size,prot) \ -direct_remap_pfn_range(vma->vm_mm,from,pfn,size,prot,DOMID_IO) +direct_remap_pfn_range(vma,from,pfn,size,prot,DOMID_IO) #define MK_IOSPACE_PFN(space, pfn) (pfn) #define GET_IOSPACE(pfn) 0 diff --git a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h index d24c5c5299..409c40483c 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h @@ -526,7 +526,7 @@ extern int kern_addr_valid(unsigned long addr); #define DOMID_LOCAL (0xFFFFU) -int direct_remap_pfn_range(struct mm_struct *mm, +int direct_remap_pfn_range(struct vm_area_struct *vma, unsigned long address, unsigned long mfn, unsigned long size, @@ -542,10 +542,10 @@ int touch_pte_range(struct mm_struct *mm, unsigned long size); #define io_remap_page_range(vma, vaddr, paddr, size, prot) \ - direct_remap_pfn_range((vma)->vm_mm,vaddr,paddr>>PAGE_SHIFT,size,prot,DOMID_IO) + direct_remap_pfn_range(vma,vaddr,(paddr)>>PAGE_SHIFT,size,prot,DOMID_IO) #define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ - direct_remap_pfn_range((vma)->vm_mm,vaddr,pfn,size,prot,DOMID_IO) + direct_remap_pfn_range(vma,vaddr,pfn,size,prot,DOMID_IO) #define MK_IOSPACE_PFN(space, pfn) (pfn) #define GET_IOSPACE(pfn) 0 From 91c8c5b1ad3e75124250935bef196b3a800f1d26 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 16 Sep 2005 12:47:40 +0000 Subject: [PATCH 2/4] Grant-refrence allocation pools and tracking tables should be per interface in netfront, not global. This fixes various bug reports including Bugzilla #183. Signed-off-by: Jim Dykman --- .../drivers/xen/netfront/netfront.c | 109 +++++++++--------- 1 file changed, 57 insertions(+), 52 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index 80534b580b..01b43aa2d2 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -59,12 +59,6 @@ #include #include -static grant_ref_t gref_tx_head; -static grant_ref_t grant_tx_ref[NETIF_TX_RING_SIZE + 1]; - -static grant_ref_t gref_rx_head; -static grant_ref_t grant_rx_ref[NETIF_RX_RING_SIZE + 1]; - #define GRANT_INVALID_REF (0xFFFF) #ifdef GRANT_DEBUG @@ -90,8 +84,6 @@ dump_packet(int tag, void *addr, u32 ap) #endif - - #ifndef __GFP_NOWARN #define __GFP_NOWARN 0 #endif @@ -187,6 +179,11 @@ struct net_private struct sk_buff *tx_skbs[NETIF_TX_RING_SIZE+1]; struct sk_buff *rx_skbs[NETIF_RX_RING_SIZE+1]; + grant_ref_t gref_tx_head; + grant_ref_t grant_tx_ref[NETIF_TX_RING_SIZE + 1]; + grant_ref_t gref_rx_head; + grant_ref_t grant_rx_ref[NETIF_TX_RING_SIZE + 1]; + struct xenbus_device *xbdev; char *backend; int backend_id; @@ -286,16 +283,16 @@ static void network_tx_buf_gc(struct net_device *dev) id = np->tx->ring[MASK_NETIF_TX_IDX(i)].resp.id; skb = np->tx_skbs[id]; #ifdef CONFIG_XEN_NETDEV_GRANT - if (unlikely(gnttab_query_foreign_access(grant_tx_ref[id]) != 0)) { + if (unlikely(gnttab_query_foreign_access(np->grant_tx_ref[id]) != 0)) { /* other domain is still using this grant - shouldn't happen but if it does, we'll try to reclaim the grant later */ printk(KERN_ALERT "network_tx_buf_gc: warning -- grant " "still in use by backend domain.\n"); goto out; } - gnttab_end_foreign_access_ref(grant_tx_ref[id], GNTMAP_readonly); - gnttab_release_grant_reference(&gref_tx_head, grant_tx_ref[id]); - grant_tx_ref[id] = GRANT_INVALID_REF; + gnttab_end_foreign_access_ref(np->grant_tx_ref[id], GNTMAP_readonly); + gnttab_release_grant_reference(&np->gref_tx_head, np->grant_tx_ref[id]); + np->grant_tx_ref[id] = GRANT_INVALID_REF; #endif ADD_ID_TO_FREELIST(np->tx_skbs, id); dev_kfree_skb_irq(skb); @@ -372,12 +369,12 @@ static void network_alloc_rx_buffers(struct net_device *dev) np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.id = id; #ifdef CONFIG_XEN_NETDEV_GRANT - ref = gnttab_claim_grant_reference(&gref_rx_head); + ref = gnttab_claim_grant_reference(&np->gref_rx_head); if (unlikely((signed short)ref < 0)) { printk(KERN_ALERT "#### netfront can't claim rx reference\n"); BUG(); } - grant_rx_ref[id] = ref; + np->grant_rx_ref[id] = ref; gnttab_grant_foreign_transfer_ref(ref, np->backend_id); np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.gref = ref; #endif @@ -470,7 +467,7 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev) tx->id = id; #ifdef CONFIG_XEN_NETDEV_GRANT - ref = gnttab_claim_grant_reference(&gref_tx_head); + ref = gnttab_claim_grant_reference(&np->gref_tx_head); if (unlikely((signed short)ref < 0)) { printk(KERN_ALERT "#### netfront can't claim tx grant reference\n"); BUG(); @@ -478,7 +475,7 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev) mfn = virt_to_mfn(skb->data); gnttab_grant_foreign_access_ref(ref, np->backend_id, mfn, GNTMAP_readonly); tx->addr = ref << PAGE_SHIFT; - grant_tx_ref[id] = ref; + np->grant_tx_ref[id] = ref; #else tx->addr = virt_to_mfn(skb->data) << PAGE_SHIFT; #endif @@ -580,7 +577,7 @@ static int netif_poll(struct net_device *dev, int *pbudget) } #ifdef CONFIG_XEN_NETDEV_GRANT - ref = grant_rx_ref[rx->id]; + ref = np->grant_rx_ref[rx->id]; if(ref == GRANT_INVALID_REF) { printk(KERN_WARNING "Bad rx grant reference %d from dom %d.\n", @@ -592,9 +589,9 @@ static int netif_poll(struct net_device *dev, int *pbudget) continue; } - grant_rx_ref[rx->id] = GRANT_INVALID_REF; + np->grant_rx_ref[rx->id] = GRANT_INVALID_REF; mfn = gnttab_end_foreign_transfer_ref(ref); - gnttab_release_grant_reference(&gref_rx_head, ref); + gnttab_release_grant_reference(&np->gref_rx_head, ref); #endif skb = np->rx_skbs[rx->id]; @@ -803,10 +800,10 @@ static void network_connect(struct net_device *dev) tx->id = i; #ifdef CONFIG_XEN_NETDEV_GRANT - gnttab_grant_foreign_access_ref(grant_tx_ref[i], np->backend_id, + gnttab_grant_foreign_access_ref(np->grant_tx_ref[i], np->backend_id, virt_to_mfn(np->tx_skbs[i]->data), GNTMAP_readonly); - tx->addr = grant_tx_ref[i] << PAGE_SHIFT; + tx->addr = np->grant_tx_ref[i] << PAGE_SHIFT; #else tx->addr = virt_to_mfn(skb->data) << PAGE_SHIFT; #endif @@ -825,8 +822,8 @@ static void network_connect(struct net_device *dev) if ((unsigned long)np->rx_skbs[i] >= __PAGE_OFFSET) { #ifdef CONFIG_XEN_NETDEV_GRANT /* Reinstate the grant ref so backend can transfer mfn to us. */ - gnttab_grant_foreign_transfer_ref(grant_rx_ref[i], np->backend_id); - np->rx->ring[requeue_idx].req.gref = grant_rx_ref[i]; + gnttab_grant_foreign_transfer_ref(np->grant_rx_ref[i], np->backend_id); + np->rx->ring[requeue_idx].req.gref = np->grant_rx_ref[i]; #endif np->rx->ring[requeue_idx].req.id = i; requeue_idx++; @@ -887,6 +884,15 @@ connect_device(struct net_private *np, unsigned int evtchn) show_device(np); } +static void netif_uninit(struct net_device *dev) +{ +#ifdef CONFIG_XEN_NETDEV_GRANT + struct net_private *np = netdev_priv(dev); + gnttab_free_grant_references(np->gref_tx_head); + gnttab_free_grant_references(np->gref_rx_head); +#endif +} + static struct ethtool_ops network_ethtool_ops = { .get_tx_csum = ethtool_op_get_tx_csum, @@ -929,22 +935,39 @@ static int create_netdev(int handle, struct xenbus_device *dev, for (i = 0; i <= NETIF_TX_RING_SIZE; i++) { np->tx_skbs[i] = (void *)((unsigned long) i+1); #ifdef CONFIG_XEN_NETDEV_GRANT - grant_tx_ref[i] = GRANT_INVALID_REF; + np->grant_tx_ref[i] = GRANT_INVALID_REF; #endif } for (i = 0; i <= NETIF_RX_RING_SIZE; i++) { np->rx_skbs[i] = (void *)((unsigned long) i+1); #ifdef CONFIG_XEN_NETDEV_GRANT - grant_rx_ref[i] = GRANT_INVALID_REF; + np->grant_rx_ref[i] = GRANT_INVALID_REF; #endif } +#ifdef CONFIG_XEN_NETDEV_GRANT + /* A grant for every tx ring slot */ + if (gnttab_alloc_grant_references(NETIF_TX_RING_SIZE, + &np->gref_tx_head) < 0) { + printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n"); + goto exit; + } + /* A grant for every rx ring slot */ + if (gnttab_alloc_grant_references(NETIF_RX_RING_SIZE, + &np->gref_rx_head) < 0) { + printk(KERN_ALERT "#### netfront can't alloc rx grant refs\n"); + gnttab_free_grant_references(np->gref_tx_head); + goto exit; + } +#endif + 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->uninit = netif_uninit; netdev->weight = 64; netdev->features = NETIF_F_IP_CSUM; @@ -952,12 +975,12 @@ static int create_netdev(int handle, struct xenbus_device *dev, if ((err = register_netdev(netdev)) != 0) { printk(KERN_WARNING "%s> register_netdev err=%d\n", __FUNCTION__, err); - goto exit; + goto exit_free_grefs; } if ((err = xennet_proc_addif(netdev)) != 0) { unregister_netdev(netdev); - goto exit; + goto exit_free_grefs; } np->netdev = netdev; @@ -968,17 +991,21 @@ static int create_netdev(int handle, struct xenbus_device *dev, else if (val != NULL) *val = netdev; return err; + + exit_free_grefs: +#ifdef CONFIG_XEN_NETDEV_GRANT + gnttab_free_grant_references(np->gref_tx_head); + gnttab_free_grant_references(np->gref_rx_head); +#endif + goto exit; } static int destroy_netdev(struct net_device *netdev) { - #ifdef CONFIG_PROC_FS xennet_proc_delif(netdev); #endif - unregister_netdev(netdev); - return 0; } @@ -1374,24 +1401,6 @@ static int __init netif_init(void) IPRINTK("Initialising virtual ethernet driver.\n"); -#ifdef CONFIG_XEN_NETDEV_GRANT - IPRINTK("Using grant tables.\n"); - - /* A grant for every tx 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; - } - /* A grant for every rx 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; - } -#endif - - (void)register_inetaddr_notifier(¬ifier_inetdev); init_net_xenbus(); @@ -1403,10 +1412,6 @@ static int __init netif_init(void) static void netif_exit(void) { -#ifdef CONFIG_XEN_NETDEV_GRANT - gnttab_free_grant_references(gref_tx_head); - gnttab_free_grant_references(gref_rx_head); -#endif } #ifdef CONFIG_PROC_FS From c9c56c71ff500980d845b31f55c130cc5cc0bbdb Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 16 Sep 2005 13:06:49 +0000 Subject: [PATCH 3/4] Clean up and re-indent netfront.c Signed-off-by: Keir Fraser --- .../drivers/xen/netfront/netfront.c | 1416 ++++++++--------- 1 file changed, 703 insertions(+), 713 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index 01b43aa2d2..bc6fa05f01 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -54,36 +54,11 @@ #include #include #include - -#ifdef CONFIG_XEN_NETDEV_GRANT #include #include #define GRANT_INVALID_REF (0xFFFF) -#ifdef GRANT_DEBUG -static void -dump_packet(int tag, void *addr, u32 ap) -{ - unsigned char *p = (unsigned char *)ap; - int i; - - printk(KERN_ALERT "#### rx_poll %c %08x ", tag & 0xff, addr); - for (i = 0; i < 20; i++) { - printk("%02x", p[i]); - } - printk("\n"); -} - -#define GDPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \ - __FILE__ , __LINE__ , ## _a ) -#else -#define dump_packet(x,y,z) ((void)0) -#define GDPRINTK(_f, _a...) ((void)0) -#endif - -#endif - #ifndef __GFP_NOWARN #define __GFP_NOWARN 0 #endif @@ -116,7 +91,6 @@ dump_packet(int tag, void *addr, u32 ap) #define NETIF_STATE_DISCONNECTED 0 #define NETIF_STATE_CONNECTED 1 - static unsigned int netif_state = NETIF_STATE_DISCONNECTED; static void network_tx_buf_gc(struct net_device *dev); @@ -139,50 +113,50 @@ static void xennet_proc_delif(struct net_device *dev); #define netfront_info net_private struct net_private { - struct list_head list; - struct net_device *netdev; + struct list_head list; + struct net_device *netdev; - struct net_device_stats stats; - NETIF_RING_IDX rx_resp_cons, tx_resp_cons; - unsigned int tx_full; + struct net_device_stats stats; + NETIF_RING_IDX rx_resp_cons, tx_resp_cons; + unsigned int tx_full; - netif_tx_interface_t *tx; - netif_rx_interface_t *rx; + netif_tx_interface_t *tx; + netif_rx_interface_t *rx; - spinlock_t tx_lock; - spinlock_t rx_lock; + spinlock_t tx_lock; + spinlock_t rx_lock; - unsigned int handle; - unsigned int evtchn; + unsigned int handle; + unsigned int evtchn; - /* What is the status of our connection to the remote backend? */ + /* What is the status of our connection to the remote backend? */ #define BEST_CLOSED 0 #define BEST_DISCONNECTED 1 #define BEST_CONNECTED 2 - unsigned int backend_state; + unsigned int backend_state; - /* Is this interface open or closed (down or up)? */ + /* Is this interface open or closed (down or up)? */ #define UST_CLOSED 0 #define UST_OPEN 1 - unsigned int user_state; + unsigned int user_state; - /* Receive-ring batched refills. */ + /* Receive-ring batched refills. */ #define RX_MIN_TARGET 8 #define RX_MAX_TARGET NETIF_RX_RING_SIZE - int rx_min_target, rx_max_target, rx_target; - struct sk_buff_head rx_batch; + int rx_min_target, rx_max_target, rx_target; + struct sk_buff_head rx_batch; - /* - * {tx,rx}_skbs store outstanding skbuffs. The first entry in each - * array is an index into a chain of free entries. - */ - struct sk_buff *tx_skbs[NETIF_TX_RING_SIZE+1]; - struct sk_buff *rx_skbs[NETIF_RX_RING_SIZE+1]; + /* + * {tx,rx}_skbs store outstanding skbuffs. The first entry in each + * array is an index into a chain of free entries. + */ + struct sk_buff *tx_skbs[NETIF_TX_RING_SIZE+1]; + struct sk_buff *rx_skbs[NETIF_RX_RING_SIZE+1]; - grant_ref_t gref_tx_head; - grant_ref_t grant_tx_ref[NETIF_TX_RING_SIZE + 1]; - grant_ref_t gref_rx_head; - grant_ref_t grant_rx_ref[NETIF_TX_RING_SIZE + 1]; + grant_ref_t gref_tx_head; + grant_ref_t grant_tx_ref[NETIF_TX_RING_SIZE + 1]; + grant_ref_t gref_rx_head; + grant_ref_t grant_rx_ref[NETIF_TX_RING_SIZE + 1]; struct xenbus_device *xbdev; char *backend; @@ -194,32 +168,32 @@ struct net_private }; /* Access macros for acquiring freeing slots in {tx,rx}_skbs[]. */ -#define ADD_ID_TO_FREELIST(_list, _id) \ - (_list)[(_id)] = (_list)[0]; \ - (_list)[0] = (void *)(unsigned long)(_id); -#define GET_ID_FROM_FREELIST(_list) \ - ({ unsigned long _id = (unsigned long)(_list)[0]; \ - (_list)[0] = (_list)[_id]; \ - (unsigned short)_id; }) +#define ADD_ID_TO_FREELIST(_list, _id) \ + (_list)[(_id)] = (_list)[0]; \ + (_list)[0] = (void *)(unsigned long)(_id); +#define GET_ID_FROM_FREELIST(_list) \ + ({ unsigned long _id = (unsigned long)(_list)[0]; \ + (_list)[0] = (_list)[_id]; \ + (unsigned short)_id; }) #ifdef DEBUG static char *be_state_name[] = { - [BEST_CLOSED] = "closed", - [BEST_DISCONNECTED] = "disconnected", - [BEST_CONNECTED] = "connected", + [BEST_CLOSED] = "closed", + [BEST_DISCONNECTED] = "disconnected", + [BEST_CONNECTED] = "connected", }; #endif #ifdef DEBUG #define DPRINTK(fmt, args...) \ - printk(KERN_ALERT "xen_net (%s:%d) " fmt, __FUNCTION__, __LINE__, ##args) + printk(KERN_ALERT "xen_net (%s:%d) " fmt, __FUNCTION__, __LINE__, ##args) #else #define DPRINTK(fmt, args...) ((void)0) #endif #define IPRINTK(fmt, args...) \ - printk(KERN_INFO "xen_net: " fmt, ##args) + printk(KERN_INFO "xen_net: " fmt, ##args) #define WPRINTK(fmt, args...) \ - printk(KERN_WARNING "xen_net: " fmt, ##args) + printk(KERN_WARNING "xen_net: " fmt, ##args) /** Send a packet on a net device to encourage switches to learn the * MAC. We send a fake ARP request. @@ -229,625 +203,627 @@ static char *be_state_name[] = { */ static int send_fake_arp(struct net_device *dev) { - struct sk_buff *skb; - u32 src_ip, dst_ip; + struct sk_buff *skb; + u32 src_ip, dst_ip; - dst_ip = INADDR_BROADCAST; - src_ip = inet_select_addr(dev, dst_ip, RT_SCOPE_LINK); + dst_ip = INADDR_BROADCAST; + src_ip = inet_select_addr(dev, dst_ip, RT_SCOPE_LINK); - /* No IP? Then nothing to do. */ - if (src_ip == 0) - return 0; + /* No IP? Then nothing to do. */ + if (src_ip == 0) + return 0; - skb = arp_create(ARPOP_REPLY, ETH_P_ARP, - dst_ip, dev, src_ip, - /*dst_hw*/ NULL, /*src_hw*/ NULL, - /*target_hw*/ dev->dev_addr); - if (skb == NULL) - return -ENOMEM; + skb = arp_create(ARPOP_REPLY, ETH_P_ARP, + dst_ip, dev, src_ip, + /*dst_hw*/ NULL, /*src_hw*/ NULL, + /*target_hw*/ dev->dev_addr); + if (skb == NULL) + return -ENOMEM; - return dev_queue_xmit(skb); + return dev_queue_xmit(skb); } static int network_open(struct net_device *dev) { - struct net_private *np = netdev_priv(dev); + struct net_private *np = netdev_priv(dev); - memset(&np->stats, 0, sizeof(np->stats)); + memset(&np->stats, 0, sizeof(np->stats)); - np->user_state = UST_OPEN; + np->user_state = UST_OPEN; - network_alloc_rx_buffers(dev); - np->rx->event = np->rx_resp_cons + 1; + network_alloc_rx_buffers(dev); + np->rx->event = np->rx_resp_cons + 1; - netif_start_queue(dev); + netif_start_queue(dev); - return 0; + return 0; } static void network_tx_buf_gc(struct net_device *dev) { - NETIF_RING_IDX i, prod; - unsigned short id; - struct net_private *np = netdev_priv(dev); - struct sk_buff *skb; + NETIF_RING_IDX i, prod; + unsigned short id; + struct net_private *np = netdev_priv(dev); + struct sk_buff *skb; - if (np->backend_state != BEST_CONNECTED) - return; + if (np->backend_state != BEST_CONNECTED) + return; - do { - prod = np->tx->resp_prod; - rmb(); /* Ensure we see responses up to 'rp'. */ + do { + prod = np->tx->resp_prod; + rmb(); /* Ensure we see responses up to 'rp'. */ - for (i = np->tx_resp_cons; i != prod; i++) { - id = np->tx->ring[MASK_NETIF_TX_IDX(i)].resp.id; - skb = np->tx_skbs[id]; + for (i = np->tx_resp_cons; i != prod; i++) { + id = np->tx->ring[MASK_NETIF_TX_IDX(i)].resp.id; + skb = np->tx_skbs[id]; #ifdef CONFIG_XEN_NETDEV_GRANT - if (unlikely(gnttab_query_foreign_access(np->grant_tx_ref[id]) != 0)) { - /* other domain is still using this grant - shouldn't happen - but if it does, we'll try to reclaim the grant later */ - printk(KERN_ALERT "network_tx_buf_gc: warning -- grant " - "still in use by backend domain.\n"); - goto out; - } - gnttab_end_foreign_access_ref(np->grant_tx_ref[id], GNTMAP_readonly); - gnttab_release_grant_reference(&np->gref_tx_head, np->grant_tx_ref[id]); - np->grant_tx_ref[id] = GRANT_INVALID_REF; + if (unlikely(gnttab_query_foreign_access(np->grant_tx_ref[id]) != 0)) { + printk(KERN_ALERT "network_tx_buf_gc: warning " + "-- grant still in use by backend " + "domain.\n"); + goto out; + } + gnttab_end_foreign_access_ref( + np->grant_tx_ref[id], GNTMAP_readonly); + gnttab_release_grant_reference( + &np->gref_tx_head, np->grant_tx_ref[id]); + np->grant_tx_ref[id] = GRANT_INVALID_REF; #endif - ADD_ID_TO_FREELIST(np->tx_skbs, id); - dev_kfree_skb_irq(skb); - } + ADD_ID_TO_FREELIST(np->tx_skbs, id); + dev_kfree_skb_irq(skb); + } - np->tx_resp_cons = prod; + np->tx_resp_cons = prod; - /* - * Set a new event, then check for race with update of tx_cons. Note - * that it is essential to schedule a callback, no matter how few - * buffers are pending. Even if there is space in the transmit ring, - * higher layers may be blocked because too much data is outstanding: - * in such cases notification from Xen is likely to be the only kick - * that we'll get. - */ - np->tx->event = - prod + ((np->tx->req_prod - prod) >> 1) + 1; - mb(); - } while (prod != np->tx->resp_prod); + /* + * Set a new event, then check for race with update of tx_cons. + * Note that it is essential to schedule a callback, no matter + * how few buffers are pending. Even if there is space in the + * transmit ring, higher layers may be blocked because too much + * data is outstanding: in such cases notification from Xen is + * likely to be the only kick that we'll get. + */ + np->tx->event = prod + ((np->tx->req_prod - prod) >> 1) + 1; + mb(); + } while (prod != np->tx->resp_prod); #ifdef CONFIG_XEN_NETDEV_GRANT - out: + out: #endif - if (np->tx_full && ((np->tx->req_prod - prod) < NETIF_TX_RING_SIZE)) { - np->tx_full = 0; - if (np->user_state == UST_OPEN) - netif_wake_queue(dev); - } + if (np->tx_full && ((np->tx->req_prod - prod) < NETIF_TX_RING_SIZE)) { + np->tx_full = 0; + if (np->user_state == UST_OPEN) + netif_wake_queue(dev); + } } static void network_alloc_rx_buffers(struct net_device *dev) { - unsigned short id; - struct net_private *np = netdev_priv(dev); - struct sk_buff *skb; - int i, batch_target; - NETIF_RING_IDX req_prod = np->rx->req_prod; - struct xen_memory_reservation reservation; + unsigned short id; + struct net_private *np = netdev_priv(dev); + struct sk_buff *skb; + int i, batch_target; + NETIF_RING_IDX req_prod = np->rx->req_prod; + struct xen_memory_reservation reservation; #ifdef CONFIG_XEN_NETDEV_GRANT - grant_ref_t ref; + grant_ref_t ref; #endif - if (unlikely(np->backend_state != BEST_CONNECTED)) - return; + if (unlikely(np->backend_state != BEST_CONNECTED)) + return; - /* - * Allocate skbuffs greedily, even though we batch updates to the - * receive ring. This creates a less bursty demand on the memory allocator, - * so should reduce the chance of failed allocation requests both for - * ourself and for other kernel subsystems. - */ - batch_target = np->rx_target - (req_prod - np->rx_resp_cons); - for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) { - if (unlikely((skb = alloc_xen_skb(dev->mtu + RX_HEADROOM)) == NULL)) - break; - __skb_queue_tail(&np->rx_batch, skb); - } + /* + * Allocate skbuffs greedily, even though we batch updates to the + * receive ring. This creates a less bursty demand on the memory + * allocator, so should reduce the chance of failed allocation requests + * both for ourself and for other kernel subsystems. + */ + batch_target = np->rx_target - (req_prod - np->rx_resp_cons); + for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) { + skb = alloc_xen_skb(dev->mtu + RX_HEADROOM); + if (skb == NULL) + break; + __skb_queue_tail(&np->rx_batch, skb); + } - /* Is the batch large enough to be worthwhile? */ - if (i < (np->rx_target/2)) - return; + /* Is the batch large enough to be worthwhile? */ + if (i < (np->rx_target/2)) + return; - for (i = 0; ; i++) { - if ((skb = __skb_dequeue(&np->rx_batch)) == NULL) - break; + for (i = 0; ; i++) { + if ((skb = __skb_dequeue(&np->rx_batch)) == NULL) + break; - skb->dev = dev; + skb->dev = dev; - id = GET_ID_FROM_FREELIST(np->rx_skbs); + id = GET_ID_FROM_FREELIST(np->rx_skbs); - np->rx_skbs[id] = skb; + np->rx_skbs[id] = skb; - np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.id = id; + np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.id = id; #ifdef CONFIG_XEN_NETDEV_GRANT - ref = gnttab_claim_grant_reference(&np->gref_rx_head); - if (unlikely((signed short)ref < 0)) { - printk(KERN_ALERT "#### netfront can't claim rx reference\n"); - BUG(); - } - np->grant_rx_ref[id] = ref; - gnttab_grant_foreign_transfer_ref(ref, np->backend_id); - np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.gref = ref; + ref = gnttab_claim_grant_reference(&np->gref_rx_head); + BUG_ON((signed short)ref < 0); + np->grant_rx_ref[id] = ref; + gnttab_grant_foreign_transfer_ref(ref, np->backend_id); + np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.gref = ref; #endif - rx_pfn_array[i] = virt_to_mfn(skb->head); + rx_pfn_array[i] = virt_to_mfn(skb->head); - /* Remove this page from pseudo phys map before passing back to Xen. */ - phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] - = INVALID_P2M_ENTRY; + /* Remove this page from map before passing back to Xen. */ + phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] + = INVALID_P2M_ENTRY; - MULTI_update_va_mapping(rx_mcl+i, (unsigned long)skb->head, - __pte(0), 0); - } + MULTI_update_va_mapping(rx_mcl+i, (unsigned long)skb->head, + __pte(0), 0); + } - /* After all PTEs have been zapped we blow away stale TLB entries. */ - rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL; + /* After all PTEs have been zapped we blow away stale TLB entries. */ + rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL; - /* Give away a batch of pages. */ - rx_mcl[i].op = __HYPERVISOR_memory_op; - rx_mcl[i].args[0] = XENMEM_decrease_reservation; - rx_mcl[i].args[1] = (unsigned long)&reservation; + /* Give away a batch of pages. */ + rx_mcl[i].op = __HYPERVISOR_memory_op; + rx_mcl[i].args[0] = XENMEM_decrease_reservation; + rx_mcl[i].args[1] = (unsigned long)&reservation; - reservation.extent_start = rx_pfn_array; - reservation.nr_extents = i; - reservation.extent_order = 0; - reservation.address_bits = 0; - reservation.domid = DOMID_SELF; + reservation.extent_start = rx_pfn_array; + reservation.nr_extents = i; + reservation.extent_order = 0; + reservation.address_bits = 0; + reservation.domid = DOMID_SELF; - /* Tell the ballon driver what is going on. */ - balloon_update_driver_allowance(i); + /* Tell the ballon driver what is going on. */ + balloon_update_driver_allowance(i); - /* Zap PTEs and give away pages in one big multicall. */ - (void)HYPERVISOR_multicall(rx_mcl, i+1); + /* Zap PTEs and give away pages in one big multicall. */ + (void)HYPERVISOR_multicall(rx_mcl, i+1); - /* Check return status of HYPERVISOR_memory_op(). */ - if (unlikely(rx_mcl[i].result != i)) - panic("Unable to reduce memory reservation\n"); + /* Check return status of HYPERVISOR_memory_op(). */ + if (unlikely(rx_mcl[i].result != i)) + panic("Unable to reduce memory reservation\n"); - /* Above is a suitable barrier to ensure backend will see requests. */ - np->rx->req_prod = req_prod + i; + /* Above is a suitable barrier to ensure backend will see requests. */ + np->rx->req_prod = req_prod + i; - /* Adjust our floating fill target if we risked running out of buffers. */ - if (((req_prod - np->rx->resp_prod) < (np->rx_target / 4)) && - ((np->rx_target *= 2) > np->rx_max_target)) - np->rx_target = np->rx_max_target; + /* Adjust our fill target if we risked running out of buffers. */ + if (((req_prod - np->rx->resp_prod) < (np->rx_target / 4)) && + ((np->rx_target *= 2) > np->rx_max_target)) + np->rx_target = np->rx_max_target; } static int network_start_xmit(struct sk_buff *skb, struct net_device *dev) { - unsigned short id; - struct net_private *np = netdev_priv(dev); - netif_tx_request_t *tx; - NETIF_RING_IDX i; + unsigned short id; + struct net_private *np = netdev_priv(dev); + netif_tx_request_t *tx; + NETIF_RING_IDX i; #ifdef CONFIG_XEN_NETDEV_GRANT - grant_ref_t ref; - unsigned long mfn; + grant_ref_t ref; + unsigned long mfn; #endif - if (unlikely(np->tx_full)) { - printk(KERN_ALERT "%s: full queue wasn't stopped!\n", dev->name); - netif_stop_queue(dev); - goto drop; - } + if (unlikely(np->tx_full)) { + printk(KERN_ALERT "%s: full queue wasn't stopped!\n", + dev->name); + netif_stop_queue(dev); + goto drop; + } - if (unlikely((((unsigned long)skb->data & ~PAGE_MASK) + skb->len) >= - PAGE_SIZE)) { - struct sk_buff *nskb; - if (unlikely((nskb = alloc_xen_skb(skb->len)) == NULL)) - goto drop; - skb_put(nskb, skb->len); - memcpy(nskb->data, skb->data, skb->len); - nskb->dev = skb->dev; - dev_kfree_skb(skb); - skb = nskb; - } + if (unlikely((((unsigned long)skb->data & ~PAGE_MASK) + skb->len) >= + PAGE_SIZE)) { + struct sk_buff *nskb; + if (unlikely((nskb = alloc_xen_skb(skb->len)) == NULL)) + goto drop; + skb_put(nskb, skb->len); + memcpy(nskb->data, skb->data, skb->len); + nskb->dev = skb->dev; + dev_kfree_skb(skb); + skb = nskb; + } - spin_lock_irq(&np->tx_lock); + spin_lock_irq(&np->tx_lock); - if (np->backend_state != BEST_CONNECTED) { - spin_unlock_irq(&np->tx_lock); - goto drop; - } + if (np->backend_state != BEST_CONNECTED) { + spin_unlock_irq(&np->tx_lock); + goto drop; + } - i = np->tx->req_prod; + i = np->tx->req_prod; - id = GET_ID_FROM_FREELIST(np->tx_skbs); - np->tx_skbs[id] = skb; + id = GET_ID_FROM_FREELIST(np->tx_skbs); + np->tx_skbs[id] = skb; - tx = &np->tx->ring[MASK_NETIF_TX_IDX(i)].req; + tx = &np->tx->ring[MASK_NETIF_TX_IDX(i)].req; - tx->id = id; + tx->id = id; #ifdef CONFIG_XEN_NETDEV_GRANT - ref = gnttab_claim_grant_reference(&np->gref_tx_head); - if (unlikely((signed short)ref < 0)) { - printk(KERN_ALERT "#### netfront can't claim tx grant reference\n"); - BUG(); - } - mfn = virt_to_mfn(skb->data); - gnttab_grant_foreign_access_ref(ref, np->backend_id, mfn, GNTMAP_readonly); - tx->addr = ref << PAGE_SHIFT; - np->grant_tx_ref[id] = ref; + ref = gnttab_claim_grant_reference(&np->gref_tx_head); + BUG_ON((signed short)ref < 0); + mfn = virt_to_mfn(skb->data); + gnttab_grant_foreign_access_ref( + ref, np->backend_id, mfn, GNTMAP_readonly); + tx->addr = ref << PAGE_SHIFT; + np->grant_tx_ref[id] = ref; #else - tx->addr = virt_to_mfn(skb->data) << PAGE_SHIFT; + tx->addr = virt_to_mfn(skb->data) << PAGE_SHIFT; #endif - tx->addr |= (unsigned long)skb->data & ~PAGE_MASK; - tx->size = skb->len; - tx->csum_blank = (skb->ip_summed == CHECKSUM_HW); + tx->addr |= (unsigned long)skb->data & ~PAGE_MASK; + tx->size = skb->len; + tx->csum_blank = (skb->ip_summed == CHECKSUM_HW); - wmb(); /* Ensure that backend will see the request. */ - np->tx->req_prod = i + 1; + wmb(); /* Ensure that backend will see the request. */ + np->tx->req_prod = i + 1; - network_tx_buf_gc(dev); + network_tx_buf_gc(dev); - if ((i - np->tx_resp_cons) == (NETIF_TX_RING_SIZE - 1)) { - np->tx_full = 1; - netif_stop_queue(dev); - } + if ((i - np->tx_resp_cons) == (NETIF_TX_RING_SIZE - 1)) { + np->tx_full = 1; + netif_stop_queue(dev); + } - spin_unlock_irq(&np->tx_lock); + spin_unlock_irq(&np->tx_lock); - np->stats.tx_bytes += skb->len; - np->stats.tx_packets++; + np->stats.tx_bytes += skb->len; + np->stats.tx_packets++; - /* Only notify Xen if we really have to. */ - mb(); - if (np->tx->TX_TEST_IDX == i) - notify_via_evtchn(np->evtchn); + /* Only notify Xen if we really have to. */ + mb(); + if (np->tx->TX_TEST_IDX == i) + notify_via_evtchn(np->evtchn); - return 0; + return 0; drop: - np->stats.tx_dropped++; - dev_kfree_skb(skb); - return 0; + np->stats.tx_dropped++; + dev_kfree_skb(skb); + return 0; } static irqreturn_t netif_int(int irq, void *dev_id, struct pt_regs *ptregs) { - struct net_device *dev = dev_id; - struct net_private *np = netdev_priv(dev); - unsigned long flags; + struct net_device *dev = dev_id; + struct net_private *np = netdev_priv(dev); + unsigned long flags; - spin_lock_irqsave(&np->tx_lock, flags); - network_tx_buf_gc(dev); - spin_unlock_irqrestore(&np->tx_lock, flags); + spin_lock_irqsave(&np->tx_lock, flags); + network_tx_buf_gc(dev); + spin_unlock_irqrestore(&np->tx_lock, flags); - if((np->rx_resp_cons != np->rx->resp_prod) && (np->user_state == UST_OPEN)) - netif_rx_schedule(dev); + if ((np->rx_resp_cons != np->rx->resp_prod) && + (np->user_state == UST_OPEN)) + netif_rx_schedule(dev); - return IRQ_HANDLED; + return IRQ_HANDLED; } static int netif_poll(struct net_device *dev, int *pbudget) { - struct net_private *np = netdev_priv(dev); - struct sk_buff *skb, *nskb; - netif_rx_response_t *rx; - NETIF_RING_IDX i, rp; - mmu_update_t *mmu = rx_mmu; - multicall_entry_t *mcl = rx_mcl; - int work_done, budget, more_to_do = 1; - struct sk_buff_head rxq; - unsigned long flags; + struct net_private *np = netdev_priv(dev); + struct sk_buff *skb, *nskb; + netif_rx_response_t *rx; + NETIF_RING_IDX i, rp; + mmu_update_t *mmu = rx_mmu; + multicall_entry_t *mcl = rx_mcl; + int work_done, budget, more_to_do = 1; + struct sk_buff_head rxq; + unsigned long flags; #ifdef CONFIG_XEN_NETDEV_GRANT - unsigned long mfn; - grant_ref_t ref; + unsigned long mfn; + grant_ref_t ref; #endif - spin_lock(&np->rx_lock); + spin_lock(&np->rx_lock); - if (np->backend_state != BEST_CONNECTED) { - spin_unlock(&np->rx_lock); - return 0; - } + if (np->backend_state != BEST_CONNECTED) { + spin_unlock(&np->rx_lock); + return 0; + } - skb_queue_head_init(&rxq); + skb_queue_head_init(&rxq); - if ((budget = *pbudget) > dev->quota) - budget = dev->quota; - rp = np->rx->resp_prod; - rmb(); /* Ensure we see queued responses up to 'rp'. */ + if ((budget = *pbudget) > dev->quota) + budget = dev->quota; + rp = np->rx->resp_prod; + rmb(); /* Ensure we see queued responses up to 'rp'. */ - for (i = np->rx_resp_cons, work_done = 0; - (i != rp) && (work_done < budget); - i++, work_done++) { - rx = &np->rx->ring[MASK_NETIF_RX_IDX(i)].resp; - /* - * An error here is very odd. Usually indicates a backend bug, - * low-memory condition, or that we didn't have reservation headroom. - */ - if (unlikely(rx->status <= 0)) { - if (net_ratelimit()) - printk(KERN_WARNING "Bad rx buffer (memory squeeze?).\n"); - np->rx->ring[MASK_NETIF_RX_IDX(np->rx->req_prod)].req.id = rx->id; - wmb(); - np->rx->req_prod++; - work_done--; - continue; - } + for (i = np->rx_resp_cons, work_done = 0; + (i != rp) && (work_done < budget); + i++, work_done++) { + rx = &np->rx->ring[MASK_NETIF_RX_IDX(i)].resp; + /* + * An error here is very odd. Usually indicates a backend bug, + * low-mem condition, or we didn't have reservation headroom. + */ + if (unlikely(rx->status <= 0)) { + if (net_ratelimit()) + printk(KERN_WARNING "Bad rx buffer " + "(memory squeeze?).\n"); + np->rx->ring[MASK_NETIF_RX_IDX(np->rx->req_prod)]. + req.id = rx->id; + wmb(); + np->rx->req_prod++; + work_done--; + continue; + } #ifdef CONFIG_XEN_NETDEV_GRANT - ref = np->grant_rx_ref[rx->id]; + ref = np->grant_rx_ref[rx->id]; - if(ref == GRANT_INVALID_REF) { - printk(KERN_WARNING "Bad rx grant reference %d from dom %d.\n", - ref, np->backend_id); - np->rx->ring[MASK_NETIF_RX_IDX(np->rx->req_prod)].req.id = rx->id; - wmb(); - np->rx->req_prod++; - work_done--; - continue; - } + if(ref == GRANT_INVALID_REF) { + printk(KERN_WARNING "Bad rx grant reference %d " + "from dom %d.\n", + ref, np->backend_id); + np->rx->ring[MASK_NETIF_RX_IDX(np->rx->req_prod)]. + req.id = rx->id; + wmb(); + np->rx->req_prod++; + work_done--; + continue; + } - np->grant_rx_ref[rx->id] = GRANT_INVALID_REF; - mfn = gnttab_end_foreign_transfer_ref(ref); - gnttab_release_grant_reference(&np->gref_rx_head, ref); + np->grant_rx_ref[rx->id] = GRANT_INVALID_REF; + mfn = gnttab_end_foreign_transfer_ref(ref); + gnttab_release_grant_reference(&np->gref_rx_head, ref); #endif - skb = np->rx_skbs[rx->id]; - ADD_ID_TO_FREELIST(np->rx_skbs, rx->id); + skb = np->rx_skbs[rx->id]; + ADD_ID_TO_FREELIST(np->rx_skbs, rx->id); - /* NB. We handle skb overflow later. */ + /* NB. We handle skb overflow later. */ #ifdef CONFIG_XEN_NETDEV_GRANT - skb->data = skb->head + rx->addr; + skb->data = skb->head + rx->addr; #else - skb->data = skb->head + (rx->addr & ~PAGE_MASK); + skb->data = skb->head + (rx->addr & ~PAGE_MASK); #endif - skb->len = rx->status; - skb->tail = skb->data + skb->len; + skb->len = rx->status; + skb->tail = skb->data + skb->len; - if ( rx->csum_valid ) - skb->ip_summed = CHECKSUM_UNNECESSARY; + if ( rx->csum_valid ) + skb->ip_summed = CHECKSUM_UNNECESSARY; - np->stats.rx_packets++; - np->stats.rx_bytes += rx->status; + np->stats.rx_packets++; + np->stats.rx_bytes += rx->status; - /* Remap the page. */ + /* Remap the page. */ #ifdef CONFIG_XEN_NETDEV_GRANT - mmu->ptr = ((unsigned long long)mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE; + mmu->ptr = ((maddr_t)mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE; #else - mmu->ptr = (rx->addr & PAGE_MASK) | MMU_MACHPHYS_UPDATE; + mmu->ptr = (rx->addr & PAGE_MASK) | MMU_MACHPHYS_UPDATE; #endif - mmu->val = __pa(skb->head) >> PAGE_SHIFT; - mmu++; + mmu->val = __pa(skb->head) >> PAGE_SHIFT; + mmu++; #ifdef CONFIG_XEN_NETDEV_GRANT - MULTI_update_va_mapping(mcl, (unsigned long)skb->head, - pfn_pte_ma(mfn, PAGE_KERNEL), 0); + MULTI_update_va_mapping(mcl, (unsigned long)skb->head, + pfn_pte_ma(mfn, PAGE_KERNEL), 0); #else - MULTI_update_va_mapping(mcl, (unsigned long)skb->head, - pfn_pte_ma(rx->addr >> PAGE_SHIFT, - PAGE_KERNEL), 0); + MULTI_update_va_mapping(mcl, (unsigned long)skb->head, + pfn_pte_ma(rx->addr >> PAGE_SHIFT, + PAGE_KERNEL), 0); #endif - mcl++; + mcl++; #ifdef CONFIG_XEN_NETDEV_GRANT - phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] = mfn; - GDPRINTK("#### rx_poll enqueue vdata=%p mfn=%lu ref=%x\n", - skb->data, mfn, ref); + phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] = mfn; #else - phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] = - rx->addr >> PAGE_SHIFT; + phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] = + rx->addr >> PAGE_SHIFT; #endif - __skb_queue_tail(&rxq, skb); - } + __skb_queue_tail(&rxq, skb); + } + /* Some pages are no longer absent... */ + balloon_update_driver_allowance(-work_done); - /* Some pages are no longer absent... */ - balloon_update_driver_allowance(-work_done); + /* Do all the remapping work, and M2P updates, in one big hypercall. */ + if (likely((mcl - rx_mcl) != 0)) { + mcl->op = __HYPERVISOR_mmu_update; + mcl->args[0] = (unsigned long)rx_mmu; + mcl->args[1] = mmu - rx_mmu; + mcl->args[2] = 0; + mcl->args[3] = DOMID_SELF; + mcl++; + (void)HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl); + } - /* Do all the remapping work, and M->P updates, in one big hypercall. */ - if (likely((mcl - rx_mcl) != 0)) { - mcl->op = __HYPERVISOR_mmu_update; - mcl->args[0] = (unsigned long)rx_mmu; - mcl->args[1] = mmu - rx_mmu; - mcl->args[2] = 0; - mcl->args[3] = DOMID_SELF; - mcl++; - (void)HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl); - } + while ((skb = __skb_dequeue(&rxq)) != NULL) { + /* + * Enough room in skbuff for the data we were passed? Also, + * Linux expects at least 16 bytes headroom in each rx buffer. + */ + if (unlikely(skb->tail > skb->end) || + unlikely((skb->data - skb->head) < 16)) { + nskb = NULL; - while ((skb = __skb_dequeue(&rxq)) != NULL) { -#ifdef CONFIG_XEN_NETDEV_GRANT - GDPRINTK("#### rx_poll dequeue vdata=%p mfn=%lu\n", - skb->data, virt_to_mfn(skb->data)); - dump_packet('d', skb->data, (unsigned long)skb->data); -#endif - /* - * Enough room in skbuff for the data we were passed? Also, Linux - * expects at least 16 bytes headroom in each receive buffer. - */ - if (unlikely(skb->tail > skb->end) || - unlikely((skb->data - skb->head) < 16)) { - nskb = NULL; + /* Only copy the packet if it fits in the MTU. */ + if (skb->len <= (dev->mtu + ETH_HLEN)) { + if ((skb->tail > skb->end) && net_ratelimit()) + printk(KERN_INFO "Received packet " + "needs %zd bytes more " + "headroom.\n", + skb->tail - skb->end); + nskb = alloc_xen_skb(skb->len + 2); + if (nskb != NULL) { + skb_reserve(nskb, 2); + skb_put(nskb, skb->len); + memcpy(nskb->data, + skb->data, + skb->len); + nskb->dev = skb->dev; + } + } + else if (net_ratelimit()) + printk(KERN_INFO "Received packet too big for " + "MTU (%d > %d)\n", + skb->len - ETH_HLEN, dev->mtu); - /* Only copy the packet if it fits in the current MTU. */ - if (skb->len <= (dev->mtu + ETH_HLEN)) { - if ((skb->tail > skb->end) && net_ratelimit()) - printk(KERN_INFO "Received packet needs %zd bytes more " - "headroom.\n", skb->tail - skb->end); + /* Reinitialise and then destroy the old skbuff. */ + skb->len = 0; + skb->tail = skb->data; + init_skb_shinfo(skb); + dev_kfree_skb(skb); - if ((nskb = alloc_xen_skb(skb->len + 2)) != NULL) { - skb_reserve(nskb, 2); - skb_put(nskb, skb->len); - memcpy(nskb->data, skb->data, skb->len); - nskb->dev = skb->dev; - } - } - else if (net_ratelimit()) - printk(KERN_INFO "Received packet too big for MTU " - "(%d > %d)\n", skb->len - ETH_HLEN, dev->mtu); - - /* Reinitialise and then destroy the old skbuff. */ - skb->len = 0; - skb->tail = skb->data; - init_skb_shinfo(skb); - dev_kfree_skb(skb); - - /* Switch old for new, if we copied the buffer. */ - if ((skb = nskb) == NULL) - continue; - } + /* Switch old for new, if we copied the buffer. */ + if ((skb = nskb) == NULL) + continue; + } - /* Set the shared-info area, which is hidden behind the real data. */ - init_skb_shinfo(skb); - /* Ethernet-specific work. Delayed to here as it peeks the header. */ - skb->protocol = eth_type_trans(skb, dev); + /* Set the shinfo area, which is hidden behind the data. */ + init_skb_shinfo(skb); + /* Ethernet work: Delayed to here as it peeks the header. */ + skb->protocol = eth_type_trans(skb, dev); - /* Pass it up. */ - netif_receive_skb(skb); - dev->last_rx = jiffies; - } + /* Pass it up. */ + netif_receive_skb(skb); + dev->last_rx = jiffies; + } - np->rx_resp_cons = i; + np->rx_resp_cons = i; - /* If we get a callback with very few responses, reduce fill target. */ - /* NB. Note exponential increase, linear decrease. */ - if (((np->rx->req_prod - np->rx->resp_prod) > ((3*np->rx_target) / 4)) && - (--np->rx_target < np->rx_min_target)) - np->rx_target = np->rx_min_target; + /* If we get a callback with very few responses, reduce fill target. */ + /* NB. Note exponential increase, linear decrease. */ + if (((np->rx->req_prod - np->rx->resp_prod) > + ((3*np->rx_target) / 4)) && + (--np->rx_target < np->rx_min_target)) + np->rx_target = np->rx_min_target; - network_alloc_rx_buffers(dev); + network_alloc_rx_buffers(dev); - *pbudget -= work_done; - dev->quota -= work_done; + *pbudget -= work_done; + dev->quota -= work_done; - if (work_done < budget) { - local_irq_save(flags); + if (work_done < budget) { + local_irq_save(flags); - np->rx->event = i + 1; + np->rx->event = i + 1; - /* Deal with hypervisor racing our resetting of rx_event. */ - mb(); - if (np->rx->resp_prod == i) { - __netif_rx_complete(dev); - more_to_do = 0; - } + /* Deal with hypervisor racing our resetting of rx_event. */ + mb(); + if (np->rx->resp_prod == i) { + __netif_rx_complete(dev); + more_to_do = 0; + } - local_irq_restore(flags); - } + local_irq_restore(flags); + } - spin_unlock(&np->rx_lock); + spin_unlock(&np->rx_lock); - return more_to_do; + return more_to_do; } static int network_close(struct net_device *dev) { - struct net_private *np = netdev_priv(dev); - np->user_state = UST_CLOSED; - netif_stop_queue(np->netdev); - return 0; + struct net_private *np = netdev_priv(dev); + np->user_state = UST_CLOSED; + netif_stop_queue(np->netdev); + return 0; } static struct net_device_stats *network_get_stats(struct net_device *dev) { - struct net_private *np = netdev_priv(dev); - return &np->stats; + struct net_private *np = netdev_priv(dev); + return &np->stats; } static void network_connect(struct net_device *dev) { - struct net_private *np; - int i, requeue_idx; - netif_tx_request_t *tx; + struct net_private *np; + int i, requeue_idx; + netif_tx_request_t *tx; - np = netdev_priv(dev); - spin_lock_irq(&np->tx_lock); - spin_lock(&np->rx_lock); + np = netdev_priv(dev); + spin_lock_irq(&np->tx_lock); + spin_lock(&np->rx_lock); - /* Recovery procedure: */ + /* Recovery procedure: */ - /* Step 1: Reinitialise variables. */ - np->rx_resp_cons = np->tx_resp_cons = np->tx_full = 0; - np->rx->event = np->tx->event = 1; + /* Step 1: Reinitialise variables. */ + np->rx_resp_cons = np->tx_resp_cons = np->tx_full = 0; + np->rx->event = np->tx->event = 1; - /* Step 2: Rebuild the RX and TX ring contents. - * NB. We could just free the queued TX packets now but we hope - * that sending them out might do some good. We have to rebuild - * the RX ring because some of our pages are currently flipped out - * so we can't just free the RX skbs. - * NB2. Freelist index entries are always going to be less than - * __PAGE_OFFSET, whereas pointers to skbs will always be equal or - * greater than __PAGE_OFFSET: we use this property to distinguish - * them. - */ + /* Step 2: Rebuild the RX and TX ring contents. + * NB. We could just free the queued TX packets now but we hope + * that sending them out might do some good. We have to rebuild + * the RX ring because some of our pages are currently flipped out + * so we can't just free the RX skbs. + * NB2. Freelist index entries are always going to be less than + * __PAGE_OFFSET, whereas pointers to skbs will always be equal or + * greater than __PAGE_OFFSET: we use this property to distinguish + * them. + */ - /* Rebuild the TX buffer freelist and the TX ring itself. - * NB. This reorders packets. We could keep more private state - * to avoid this but maybe it doesn't matter so much given the - * interface has been down. - */ - for (requeue_idx = 0, i = 1; i <= NETIF_TX_RING_SIZE; i++) { - if ((unsigned long)np->tx_skbs[i] >= __PAGE_OFFSET) { - struct sk_buff *skb = np->tx_skbs[i]; + /* Rebuild the TX buffer freelist and the TX ring itself. + * NB. This reorders packets. We could keep more private state + * to avoid this but maybe it doesn't matter so much given the + * interface has been down. + */ + for (requeue_idx = 0, i = 1; i <= NETIF_TX_RING_SIZE; i++) { + if ((unsigned long)np->tx_skbs[i] >= __PAGE_OFFSET) { + struct sk_buff *skb = np->tx_skbs[i]; - tx = &np->tx->ring[requeue_idx++].req; + tx = &np->tx->ring[requeue_idx++].req; - tx->id = i; + tx->id = i; #ifdef CONFIG_XEN_NETDEV_GRANT - gnttab_grant_foreign_access_ref(np->grant_tx_ref[i], np->backend_id, - virt_to_mfn(np->tx_skbs[i]->data), - GNTMAP_readonly); - tx->addr = np->grant_tx_ref[i] << PAGE_SHIFT; + gnttab_grant_foreign_access_ref( + np->grant_tx_ref[i], np->backend_id, + virt_to_mfn(np->tx_skbs[i]->data), + GNTMAP_readonly); + tx->addr = np->grant_tx_ref[i] << PAGE_SHIFT; #else - tx->addr = virt_to_mfn(skb->data) << PAGE_SHIFT; + tx->addr = virt_to_mfn(skb->data) << PAGE_SHIFT; #endif - tx->addr |= (unsigned long)skb->data & ~PAGE_MASK; - tx->size = skb->len; + tx->addr |= (unsigned long)skb->data & ~PAGE_MASK; + tx->size = skb->len; - np->stats.tx_bytes += skb->len; - np->stats.tx_packets++; - } - } - wmb(); - np->tx->req_prod = requeue_idx; + np->stats.tx_bytes += skb->len; + np->stats.tx_packets++; + } + } + wmb(); + np->tx->req_prod = requeue_idx; - /* Rebuild the RX buffer freelist and the RX ring itself. */ - for (requeue_idx = 0, i = 1; i <= NETIF_RX_RING_SIZE; i++) { - if ((unsigned long)np->rx_skbs[i] >= __PAGE_OFFSET) { + /* Rebuild the RX buffer freelist and the RX ring itself. */ + for (requeue_idx = 0, i = 1; i <= NETIF_RX_RING_SIZE; i++) { + if ((unsigned long)np->rx_skbs[i] >= __PAGE_OFFSET) { #ifdef CONFIG_XEN_NETDEV_GRANT - /* Reinstate the grant ref so backend can transfer mfn to us. */ - gnttab_grant_foreign_transfer_ref(np->grant_rx_ref[i], np->backend_id); - np->rx->ring[requeue_idx].req.gref = np->grant_rx_ref[i]; + gnttab_grant_foreign_transfer_ref( + np->grant_rx_ref[i], np->backend_id); + np->rx->ring[requeue_idx].req.gref = + np->grant_rx_ref[i]; #endif - np->rx->ring[requeue_idx].req.id = i; - requeue_idx++; - } - } + np->rx->ring[requeue_idx].req.id = i; + requeue_idx++; + } + } - wmb(); - np->rx->req_prod = requeue_idx; + wmb(); + np->rx->req_prod = requeue_idx; - /* Step 3: All public and private state should now be sane. Get - * ready to start sending and receiving packets and give the driver - * domain a kick because we've probably just requeued some - * packets. - */ - np->backend_state = BEST_CONNECTED; - wmb(); - notify_via_evtchn(np->evtchn); - network_tx_buf_gc(dev); + /* Step 3: All public and private state should now be sane. Get + * ready to start sending and receiving packets and give the driver + * domain a kick because we've probably just requeued some + * packets. + */ + np->backend_state = BEST_CONNECTED; + wmb(); + notify_via_evtchn(np->evtchn); + network_tx_buf_gc(dev); - if (np->user_state == UST_OPEN) - netif_start_queue(dev); + if (np->user_state == UST_OPEN) + netif_start_queue(dev); - spin_unlock(&np->rx_lock); - spin_unlock_irq(&np->tx_lock); + spin_unlock(&np->rx_lock); + spin_unlock_irq(&np->tx_lock); } static void show_device(struct net_private *np) @@ -887,9 +863,9 @@ connect_device(struct net_private *np, unsigned int evtchn) static void netif_uninit(struct net_device *dev) { #ifdef CONFIG_XEN_NETDEV_GRANT - struct net_private *np = netdev_priv(dev); - gnttab_free_grant_references(np->gref_tx_head); - gnttab_free_grant_references(np->gref_rx_head); + struct net_private *np = netdev_priv(dev); + gnttab_free_grant_references(np->gref_tx_head); + gnttab_free_grant_references(np->gref_rx_head); #endif } @@ -907,97 +883,99 @@ static struct ethtool_ops network_ethtool_ops = static int create_netdev(int handle, struct xenbus_device *dev, struct net_device **val) { - int i, err = 0; - struct net_device *netdev = NULL; - struct net_private *np = NULL; + int i, err = 0; + struct net_device *netdev = NULL; + struct net_private *np = NULL; - if ((netdev = alloc_etherdev(sizeof(struct net_private))) == NULL) { - printk(KERN_WARNING "%s> alloc_etherdev failed.\n", __FUNCTION__); - err = -ENOMEM; - goto exit; - } + 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(netdev); - np->backend_state = BEST_CLOSED; - np->user_state = UST_CLOSED; - np->handle = handle; - np->xbdev = 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); + spin_lock_init(&np->tx_lock); + spin_lock_init(&np->rx_lock); - skb_queue_head_init(&np->rx_batch); - np->rx_target = RX_MIN_TARGET; - np->rx_min_target = RX_MIN_TARGET; - np->rx_max_target = RX_MAX_TARGET; + skb_queue_head_init(&np->rx_batch); + np->rx_target = RX_MIN_TARGET; + np->rx_min_target = RX_MIN_TARGET; + np->rx_max_target = RX_MAX_TARGET; - /* Initialise {tx,rx}_skbs to be a free chain containing every entry. */ - for (i = 0; i <= NETIF_TX_RING_SIZE; i++) { - np->tx_skbs[i] = (void *)((unsigned long) i+1); + /* Initialise {tx,rx}_skbs as a free chain containing every entry. */ + for (i = 0; i <= NETIF_TX_RING_SIZE; i++) { + np->tx_skbs[i] = (void *)((unsigned long) i+1); #ifdef CONFIG_XEN_NETDEV_GRANT - np->grant_tx_ref[i] = GRANT_INVALID_REF; + np->grant_tx_ref[i] = GRANT_INVALID_REF; #endif - } + } - for (i = 0; i <= NETIF_RX_RING_SIZE; i++) { - np->rx_skbs[i] = (void *)((unsigned long) i+1); + for (i = 0; i <= NETIF_RX_RING_SIZE; i++) { + np->rx_skbs[i] = (void *)((unsigned long) i+1); #ifdef CONFIG_XEN_NETDEV_GRANT - np->grant_rx_ref[i] = GRANT_INVALID_REF; + np->grant_rx_ref[i] = GRANT_INVALID_REF; #endif - } + } #ifdef CONFIG_XEN_NETDEV_GRANT - /* A grant for every tx ring slot */ - if (gnttab_alloc_grant_references(NETIF_TX_RING_SIZE, - &np->gref_tx_head) < 0) { - printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n"); - goto exit; - } - /* A grant for every rx ring slot */ - if (gnttab_alloc_grant_references(NETIF_RX_RING_SIZE, - &np->gref_rx_head) < 0) { - printk(KERN_ALERT "#### netfront can't alloc rx grant refs\n"); - gnttab_free_grant_references(np->gref_tx_head); - goto exit; - } + /* A grant for every tx ring slot */ + if (gnttab_alloc_grant_references(NETIF_TX_RING_SIZE, + &np->gref_tx_head) < 0) { + printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n"); + goto exit; + } + /* A grant for every rx ring slot */ + if (gnttab_alloc_grant_references(NETIF_RX_RING_SIZE, + &np->gref_rx_head) < 0) { + printk(KERN_ALERT "#### netfront can't alloc rx grant refs\n"); + gnttab_free_grant_references(np->gref_tx_head); + goto exit; + } #endif - 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->uninit = netif_uninit; - netdev->weight = 64; - netdev->features = NETIF_F_IP_CSUM; + 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->uninit = netif_uninit; + netdev->weight = 64; + netdev->features = NETIF_F_IP_CSUM; - SET_ETHTOOL_OPS(netdev, &network_ethtool_ops); + 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_free_grefs; - } + if ((err = register_netdev(netdev)) != 0) { + printk(KERN_WARNING "%s> register_netdev err=%d\n", + __FUNCTION__, err); + goto exit_free_grefs; + } - if ((err = xennet_proc_addif(netdev)) != 0) { - unregister_netdev(netdev); - goto exit_free_grefs; - } + if ((err = xennet_proc_addif(netdev)) != 0) { + unregister_netdev(netdev); + goto exit_free_grefs; + } - np->netdev = netdev; + np->netdev = netdev; - exit: - if ((err != 0) && (netdev != NULL)) - kfree(netdev); - else if (val != NULL) - *val = netdev; - return err; + exit: + if ((err != 0) && (netdev != NULL)) + kfree(netdev); + else if (val != NULL) + *val = netdev; + return err; exit_free_grefs: #ifdef CONFIG_XEN_NETDEV_GRANT - gnttab_free_grant_references(np->gref_tx_head); - gnttab_free_grant_references(np->gref_rx_head); + gnttab_free_grant_references(np->gref_tx_head); + gnttab_free_grant_references(np->gref_rx_head); #endif - goto exit; + goto exit; } static int destroy_netdev(struct net_device *netdev) @@ -1016,20 +994,20 @@ static int destroy_netdev(struct net_device *netdev) static int inetdev_notify(struct notifier_block *this, unsigned long event, void *ptr) { - struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; - struct net_device *dev = ifa->ifa_dev->dev; + struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; + struct net_device *dev = ifa->ifa_dev->dev; - /* UP event and is it one of our devices? */ - if (event == NETDEV_UP && dev->open == network_open) - (void)send_fake_arp(dev); + /* UP event and is it one of our devices? */ + if (event == NETDEV_UP && dev->open == network_open) + (void)send_fake_arp(dev); - return NOTIFY_DONE; + return NOTIFY_DONE; } static struct notifier_block notifier_inetdev = { - .notifier_call = inetdev_notify, - .next = NULL, - .priority = 0 + .notifier_call = inetdev_notify, + .next = NULL, + .priority = 0 }; static struct xenbus_device_id netfront_ids[] = { @@ -1368,46 +1346,46 @@ static void __init init_net_xenbus(void) static int wait_for_netif(void) { - int err = 0; - int i; + int err = 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; netif_state != NETIF_STATE_CONNECTED && (i < 10*HZ); i++ ) - { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } + /* + * 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; netif_state != NETIF_STATE_CONNECTED && (i < 10*HZ); i++ ) + { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + } - if (netif_state != NETIF_STATE_CONNECTED) { - WPRINTK("Timeout connecting to device!\n"); - err = -ENOSYS; - } - return err; + if (netif_state != NETIF_STATE_CONNECTED) { + WPRINTK("Timeout connecting to device!\n"); + err = -ENOSYS; + } + return err; } static int __init netif_init(void) { - int err = 0; + int err = 0; - if (xen_start_info->flags & SIF_INITDOMAIN) - return 0; + if (xen_start_info->flags & SIF_INITDOMAIN) + return 0; - if ((err = xennet_proc_init()) != 0) - return err; + if ((err = xennet_proc_init()) != 0) + return err; - IPRINTK("Initialising virtual ethernet driver.\n"); + IPRINTK("Initialising virtual ethernet driver.\n"); - (void)register_inetaddr_notifier(¬ifier_inetdev); + (void)register_inetaddr_notifier(¬ifier_inetdev); - init_net_xenbus(); + init_net_xenbus(); - wait_for_netif(); + wait_for_netif(); - return err; + return err; } static void netif_exit(void) @@ -1421,147 +1399,159 @@ static void netif_exit(void) #define TARGET_CUR 2UL static int xennet_proc_read( - char *page, char **start, off_t off, int count, int *eof, void *data) + char *page, char **start, off_t off, int count, int *eof, void *data) { - struct net_device *dev = (struct net_device *)((unsigned long)data & ~3UL); - struct net_private *np = netdev_priv(dev); - int len = 0, which_target = (long)data & 3; + struct net_device *dev = + (struct net_device *)((unsigned long)data & ~3UL); + struct net_private *np = netdev_priv(dev); + int len = 0, which_target = (long)data & 3; - switch (which_target) - { - case TARGET_MIN: - len = sprintf(page, "%d\n", np->rx_min_target); - break; - case TARGET_MAX: - len = sprintf(page, "%d\n", np->rx_max_target); - break; - case TARGET_CUR: - len = sprintf(page, "%d\n", np->rx_target); - break; - } + switch (which_target) + { + case TARGET_MIN: + len = sprintf(page, "%d\n", np->rx_min_target); + break; + case TARGET_MAX: + len = sprintf(page, "%d\n", np->rx_max_target); + break; + case TARGET_CUR: + len = sprintf(page, "%d\n", np->rx_target); + break; + } - *eof = 1; - return len; + *eof = 1; + return len; } static int xennet_proc_write( - struct file *file, const char __user *buffer, - unsigned long count, void *data) + struct file *file, const char __user *buffer, + unsigned long count, void *data) { - struct net_device *dev = (struct net_device *)((unsigned long)data & ~3UL); - struct net_private *np = netdev_priv(dev); - int which_target = (long)data & 3; - char string[64]; - long target; + struct net_device *dev = + (struct net_device *)((unsigned long)data & ~3UL); + struct net_private *np = netdev_priv(dev); + int which_target = (long)data & 3; + char string[64]; + long target; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; - if (count <= 1) - return -EBADMSG; /* runt */ - if (count > sizeof(string)) - return -EFBIG; /* too long */ + if (count <= 1) + return -EBADMSG; /* runt */ + if (count > sizeof(string)) + return -EFBIG; /* too long */ - if (copy_from_user(string, buffer, count)) - return -EFAULT; - string[sizeof(string)-1] = '\0'; + if (copy_from_user(string, buffer, count)) + return -EFAULT; + string[sizeof(string)-1] = '\0'; - target = simple_strtol(string, NULL, 10); - if (target < RX_MIN_TARGET) - target = RX_MIN_TARGET; - if (target > RX_MAX_TARGET) - target = RX_MAX_TARGET; + target = simple_strtol(string, NULL, 10); + if (target < RX_MIN_TARGET) + target = RX_MIN_TARGET; + if (target > RX_MAX_TARGET) + target = RX_MAX_TARGET; - spin_lock(&np->rx_lock); + spin_lock(&np->rx_lock); - switch (which_target) - { - case TARGET_MIN: - if (target > np->rx_max_target) - np->rx_max_target = target; - np->rx_min_target = target; - if (target > np->rx_target) - np->rx_target = target; - break; - case TARGET_MAX: - if (target < np->rx_min_target) - np->rx_min_target = target; - np->rx_max_target = target; - if (target < np->rx_target) - np->rx_target = target; - break; - case TARGET_CUR: - break; - } + switch (which_target) + { + case TARGET_MIN: + if (target > np->rx_max_target) + np->rx_max_target = target; + np->rx_min_target = target; + if (target > np->rx_target) + np->rx_target = target; + break; + case TARGET_MAX: + if (target < np->rx_min_target) + np->rx_min_target = target; + np->rx_max_target = target; + if (target < np->rx_target) + np->rx_target = target; + break; + case TARGET_CUR: + break; + } - network_alloc_rx_buffers(dev); + network_alloc_rx_buffers(dev); - spin_unlock(&np->rx_lock); + spin_unlock(&np->rx_lock); - return count; + return count; } static int xennet_proc_init(void) { - if (proc_mkdir("xen/net", NULL) == NULL) - return -ENOMEM; - return 0; + if (proc_mkdir("xen/net", NULL) == NULL) + return -ENOMEM; + return 0; } static int xennet_proc_addif(struct net_device *dev) { - struct proc_dir_entry *dir, *min, *max, *cur; - char name[30]; + struct proc_dir_entry *dir, *min, *max, *cur; + char name[30]; - sprintf(name, "xen/net/%s", dev->name); + sprintf(name, "xen/net/%s", dev->name); - dir = proc_mkdir(name, NULL); - if (!dir) - goto nomem; + dir = proc_mkdir(name, NULL); + if (!dir) + goto nomem; - min = create_proc_entry("rxbuf_min", 0644, dir); - max = create_proc_entry("rxbuf_max", 0644, dir); - cur = create_proc_entry("rxbuf_cur", 0444, dir); - if (!min || !max || !cur) - goto nomem; + min = create_proc_entry("rxbuf_min", 0644, dir); + max = create_proc_entry("rxbuf_max", 0644, dir); + cur = create_proc_entry("rxbuf_cur", 0444, dir); + if (!min || !max || !cur) + goto nomem; - min->read_proc = xennet_proc_read; - min->write_proc = xennet_proc_write; - min->data = (void *)((unsigned long)dev | TARGET_MIN); + min->read_proc = xennet_proc_read; + min->write_proc = xennet_proc_write; + min->data = (void *)((unsigned long)dev | TARGET_MIN); - max->read_proc = xennet_proc_read; - max->write_proc = xennet_proc_write; - max->data = (void *)((unsigned long)dev | TARGET_MAX); + max->read_proc = xennet_proc_read; + max->write_proc = xennet_proc_write; + max->data = (void *)((unsigned long)dev | TARGET_MAX); - cur->read_proc = xennet_proc_read; - cur->write_proc = xennet_proc_write; - cur->data = (void *)((unsigned long)dev | TARGET_CUR); + cur->read_proc = xennet_proc_read; + cur->write_proc = xennet_proc_write; + cur->data = (void *)((unsigned long)dev | TARGET_CUR); - return 0; + return 0; nomem: - xennet_proc_delif(dev); - return -ENOMEM; + xennet_proc_delif(dev); + return -ENOMEM; } static void xennet_proc_delif(struct net_device *dev) { - char name[30]; + char name[30]; - sprintf(name, "xen/net/%s/rxbuf_min", dev->name); - remove_proc_entry(name, NULL); + sprintf(name, "xen/net/%s/rxbuf_min", dev->name); + remove_proc_entry(name, NULL); - sprintf(name, "xen/net/%s/rxbuf_max", dev->name); - remove_proc_entry(name, NULL); + sprintf(name, "xen/net/%s/rxbuf_max", dev->name); + remove_proc_entry(name, NULL); - sprintf(name, "xen/net/%s/rxbuf_cur", dev->name); - remove_proc_entry(name, NULL); + sprintf(name, "xen/net/%s/rxbuf_cur", dev->name); + remove_proc_entry(name, NULL); - sprintf(name, "xen/net/%s", dev->name); - remove_proc_entry(name, NULL); + sprintf(name, "xen/net/%s", dev->name); + remove_proc_entry(name, NULL); } #endif module_init(netif_init); module_exit(netif_exit); + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ From e36a02461dd906dbb1f4454cf333f051863dd0b2 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 16 Sep 2005 13:27:01 +0000 Subject: [PATCH 4/4] Clean up and re-indent netback driver. Signed-off-by: Keir Fraser --- .../drivers/xen/netback/common.h | 103 +- .../drivers/xen/netback/interface.c | 420 +++--- .../drivers/xen/netback/netback.c | 1230 +++++++++-------- .../drivers/xen/netback/xenbus.c | 10 + 4 files changed, 898 insertions(+), 865 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/common.h b/linux-2.6-xen-sparse/drivers/xen/netback/common.h index ed8fb6a861..77a8681abf 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h +++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h @@ -18,17 +18,11 @@ #include #include #include - -#ifdef CONFIG_XEN_NETDEV_GRANT #include #include #define GRANT_INVALID_REF (0xFFFF) -#endif - - - #if 0 #define ASSERT(_p) \ if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \ @@ -44,74 +38,73 @@ #define WPRINTK(fmt, args...) \ printk(KERN_WARNING "xen_net: " fmt, ##args) - typedef struct netif_st { - /* Unique identifier for this interface. */ - domid_t domid; - unsigned int handle; + /* Unique identifier for this interface. */ + domid_t domid; + unsigned int handle; - u8 fe_dev_addr[6]; + u8 fe_dev_addr[6]; - /* Physical parameters of the comms window. */ - unsigned long tx_shmem_frame; + /* Physical parameters of the comms window. */ + unsigned long tx_shmem_frame; #ifdef CONFIG_XEN_NETDEV_GRANT - u16 tx_shmem_handle; - unsigned long tx_shmem_vaddr; - grant_ref_t tx_shmem_ref; + u16 tx_shmem_handle; + unsigned long tx_shmem_vaddr; + grant_ref_t tx_shmem_ref; #endif - unsigned long rx_shmem_frame; + unsigned long rx_shmem_frame; #ifdef CONFIG_XEN_NETDEV_GRANT - u16 rx_shmem_handle; - unsigned long rx_shmem_vaddr; - grant_ref_t rx_shmem_ref; + u16 rx_shmem_handle; + unsigned long rx_shmem_vaddr; + grant_ref_t rx_shmem_ref; #endif - unsigned int evtchn; - unsigned int remote_evtchn; + unsigned int evtchn; + unsigned int remote_evtchn; - /* The shared rings and indexes. */ - netif_tx_interface_t *tx; - netif_rx_interface_t *rx; + /* 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 */ + /* Private indexes into shared ring. */ + NETIF_RING_IDX rx_req_cons; + NETIF_RING_IDX rx_resp_prod; /* private version of shared variable */ #ifdef CONFIG_XEN_NETDEV_GRANT - NETIF_RING_IDX rx_resp_prod_copy; /* private version of shared variable */ + NETIF_RING_IDX rx_resp_prod_copy; #endif - NETIF_RING_IDX tx_req_cons; - NETIF_RING_IDX tx_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; + /* 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; - int active; - struct list_head list; /* scheduling list */ - atomic_t refcnt; - struct net_device *dev; - struct net_device_stats stats; + /* Miscellaneous private stuff. */ + enum { DISCONNECTED, DISCONNECTING, CONNECTED } status; + int active; + struct list_head list; /* scheduling list */ + atomic_t refcnt; + struct net_device *dev; + struct net_device_stats stats; - struct work_struct free_work; + struct work_struct free_work; } netif_t; void netif_creditlimit(netif_t *netif); int netif_disconnect(netif_t *netif); netif_t *alloc_netif(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN]); -void free_netif_callback(netif_t *netif); +void free_netif(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) ) \ - free_netif_callback(_b); \ - } while (0) +#define netif_put(_b) \ + do { \ + if ( atomic_dec_and_test(&(_b)->refcnt) ) \ + free_netif(_b); \ + } while (0) void netif_xenbus_init(void); @@ -123,3 +116,13 @@ struct net_device_stats *netif_be_get_stats(struct net_device *dev); irqreturn_t netif_be_int(int irq, void *dev_id, struct pt_regs *regs); #endif /* __NETIF__BACKEND__COMMON_H__ */ + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c index 8b42041e62..311f426d0b 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c @@ -11,104 +11,105 @@ static void __netif_up(netif_t *netif) { - struct net_device *dev = netif->dev; - spin_lock_bh(&dev->xmit_lock); - netif->active = 1; - spin_unlock_bh(&dev->xmit_lock); - (void)bind_evtchn_to_irqhandler( - netif->evtchn, netif_be_int, 0, dev->name, netif); - netif_schedule_work(netif); + struct net_device *dev = netif->dev; + spin_lock_bh(&dev->xmit_lock); + netif->active = 1; + spin_unlock_bh(&dev->xmit_lock); + (void)bind_evtchn_to_irqhandler( + netif->evtchn, netif_be_int, 0, dev->name, netif); + netif_schedule_work(netif); } static void __netif_down(netif_t *netif) { - struct net_device *dev = netif->dev; - spin_lock_bh(&dev->xmit_lock); - netif->active = 0; - spin_unlock_bh(&dev->xmit_lock); - unbind_evtchn_from_irqhandler(netif->evtchn, netif); - netif_deschedule_work(netif); + struct net_device *dev = netif->dev; + spin_lock_bh(&dev->xmit_lock); + netif->active = 0; + spin_unlock_bh(&dev->xmit_lock); + unbind_evtchn_from_irqhandler(netif->evtchn, netif); + netif_deschedule_work(netif); } static int net_open(struct net_device *dev) { - netif_t *netif = netdev_priv(dev); - if (netif->status == CONNECTED) - __netif_up(netif); - netif_start_queue(dev); - return 0; + netif_t *netif = netdev_priv(dev); + if (netif->status == CONNECTED) + __netif_up(netif); + netif_start_queue(dev); + return 0; } static int net_close(struct net_device *dev) { - netif_t *netif = netdev_priv(dev); - netif_stop_queue(dev); - if (netif->status == CONNECTED) - __netif_down(netif); - return 0; + netif_t *netif = netdev_priv(dev); + netif_stop_queue(dev); + if (netif->status == CONNECTED) + __netif_down(netif); + return 0; } 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 *netif; - char name[IFNAMSIZ] = {}; + int err = 0, i; + struct net_device *dev; + netif_t *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"); - return NULL; - } + 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"); + return NULL; + } - netif = netdev_priv(dev); - memset(netif, 0, sizeof(*netif)); - netif->domid = domid; - netif->handle = handle; - netif->status = DISCONNECTED; - atomic_set(&netif->refcnt, 0); - netif->dev = dev; + netif = netdev_priv(dev); + memset(netif, 0, sizeof(*netif)); + netif->domid = domid; + netif->handle = handle; + netif->status = DISCONNECTED; + atomic_set(&netif->refcnt, 0); + netif->dev = dev; - netif->credit_bytes = netif->remaining_credit = ~0UL; - netif->credit_usec = 0UL; - init_timer(&netif->credit_timeout); + netif->credit_bytes = netif->remaining_credit = ~0UL; + netif->credit_usec = 0UL; + init_timer(&netif->credit_timeout); - dev->hard_start_xmit = netif_be_start_xmit; - dev->get_stats = netif_be_get_stats; - dev->open = net_open; - dev->stop = net_close; - dev->features = NETIF_F_NO_CSUM; + dev->hard_start_xmit = netif_be_start_xmit; + dev->get_stats = netif_be_get_stats; + dev->open = net_open; + dev->stop = net_close; + dev->features = NETIF_F_NO_CSUM; - /* Disable queuing. */ - dev->tx_queue_len = 0; + /* Disable queuing. */ + dev->tx_queue_len = 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 - * non-broadcast address to prevent the address getting stolen by an - * Ethernet bridge for STP purposes. (FE:FF:FF:FF:FF:FF) - */ - memset(dev->dev_addr, 0xFF, ETH_ALEN); - dev->dev_addr[0] &= ~0x01; - } else - memcpy(dev->dev_addr, be_mac, ETH_ALEN); + 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 non-broadcast address to prevent the address getting + * stolen by an Ethernet bridge for STP purposes. + * (FE:FF:FF:FF:FF:FF) + */ + memset(dev->dev_addr, 0xFF, ETH_ALEN); + dev->dev_addr[0] &= ~0x01; + } else + memcpy(dev->dev_addr, be_mac, ETH_ALEN); - rtnl_lock(); - err = register_netdevice(dev); - rtnl_unlock(); - if (err) { - DPRINTK("Could not register new net device %s: err=%d\n", - dev->name, err); - free_netdev(dev); - return NULL; - } + rtnl_lock(); + err = register_netdevice(dev); + rtnl_unlock(); + if (err) { + DPRINTK("Could not register new net device %s: err=%d\n", + dev->name, err); + free_netdev(dev); + return NULL; + } - DPRINTK("Successfully created netif\n"); - return netif; + DPRINTK("Successfully created netif\n"); + return netif; } static int map_frontend_pages(netif_t *netif, unsigned long localaddr, @@ -116,191 +117,204 @@ static int map_frontend_pages(netif_t *netif, unsigned long localaddr, unsigned long rx_ring_ref) { #ifdef CONFIG_XEN_NETDEV_GRANT - struct gnttab_map_grant_ref op; + 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; + /* 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 mapping tx_ring_ref!\n"); - return op.handle; - } + BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) ); + if (op.handle < 0) { + DPRINTK(" Gnttab failure mapping tx_ring_ref!\n"); + return op.handle; + } - netif->tx_shmem_ref = tx_ring_ref; - netif->tx_shmem_handle = op.handle; - netif->tx_shmem_vaddr = localaddr; + netif->tx_shmem_ref = tx_ring_ref; + netif->tx_shmem_handle = op.handle; + netif->tx_shmem_vaddr = localaddr; - /* 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; + /* 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 mapping rx_ring_ref!\n"); - return op.handle; - } + BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) ); + if (op.handle < 0) { + DPRINTK(" Gnttab failure mapping rx_ring_ref!\n"); + return op.handle; + } - netif->rx_shmem_ref = rx_ring_ref; - netif->rx_shmem_handle = op.handle; - netif->rx_shmem_vaddr = localaddr + PAGE_SIZE; + netif->rx_shmem_ref = rx_ring_ref; + netif->rx_shmem_handle = op.handle; + netif->rx_shmem_vaddr = localaddr + PAGE_SIZE; #else - pgprot_t prot = __pgprot(_KERNPG_TABLE); - int err; + pgprot_t prot = __pgprot(_KERNPG_TABLE); + int err; - err = direct_remap_pfn_range(&init_mm, localaddr, - tx_ring_ref, PAGE_SIZE, - prot, netif->domid); + err = direct_remap_pfn_range( + &init_mm, localaddr, + tx_ring_ref, PAGE_SIZE, + prot, netif->domid); - err |= direct_remap_pfn_range(&init_mm, localaddr + PAGE_SIZE, - rx_ring_ref, PAGE_SIZE, - prot, netif->domid); + err |= direct_remap_pfn_range( + &init_mm, localaddr + PAGE_SIZE, + rx_ring_ref, PAGE_SIZE, + prot, netif->domid); - if (err) - return err; + if (err) + return err; #endif - return 0; + return 0; } static void unmap_frontend_pages(netif_t *netif) { #ifdef CONFIG_XEN_NETDEV_GRANT - struct gnttab_unmap_grant_ref op; + struct gnttab_unmap_grant_ref op; - 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)); + 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)); - 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)); + 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 - return; + return; } 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; + struct vm_struct *vma; + evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain }; + int err; - vma = get_vm_area(2*PAGE_SIZE, VM_IOREMAP); - if (vma == NULL) - return -ENOMEM; + vma = get_vm_area(2*PAGE_SIZE, VM_IOREMAP); + if (vma == NULL) + return -ENOMEM; - err = map_frontend_pages(netif, (unsigned long)vma->addr, tx_ring_ref, - rx_ring_ref); - if (err) { - vfree(vma->addr); - return err; - } + err = map_frontend_pages( + 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_pages(netif); - 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_pages(netif); + vfree(vma->addr); + return err; + } - netif->evtchn = op.u.bind_interdomain.port1; - netif->remote_evtchn = evtchn; + netif->evtchn = op.u.bind_interdomain.port1; + netif->remote_evtchn = evtchn; - 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. */ + 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(); + rtnl_lock(); + netif->status = CONNECTED; + wmb(); + if (netif_running(netif->dev)) + __netif_up(netif); + rtnl_unlock(); - return 0; + return 0; } -static void free_netif(void *arg) +static void free_netif_callback(void *arg) { - evtchn_op_t op = { .cmd = EVTCHNOP_close }; - netif_t *netif = (netif_t *)arg; + evtchn_op_t op = { .cmd = EVTCHNOP_close }; + 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. - */ + /* + * 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. + */ - op.u.close.port = netif->evtchn; - op.u.close.dom = DOMID_SELF; - HYPERVISOR_event_channel_op(&op); - op.u.close.port = netif->remote_evtchn; - op.u.close.dom = netif->domid; - HYPERVISOR_event_channel_op(&op); + op.u.close.port = netif->evtchn; + op.u.close.dom = DOMID_SELF; + HYPERVISOR_event_channel_op(&op); + op.u.close.port = netif->remote_evtchn; + op.u.close.dom = netif->domid; + HYPERVISOR_event_channel_op(&op); - unregister_netdev(netif->dev); + unregister_netdev(netif->dev); - if (netif->tx) { - unmap_frontend_pages(netif); - vfree(netif->tx); /* Frees netif->rx as well. */ - } + if (netif->tx) { + unmap_frontend_pages(netif); + vfree(netif->tx); /* Frees netif->rx as well. */ + } - free_netdev(netif->dev); + free_netdev(netif->dev); } -void free_netif_callback(netif_t *netif) +void free_netif(netif_t *netif) { - INIT_WORK(&netif->free_work, free_netif, (void *)netif); - schedule_work(&netif->free_work); + INIT_WORK(&netif->free_work, free_netif_callback, (void *)netif); + schedule_work(&netif->free_work); } void netif_creditlimit(netif_t *netif) { #if 0 - /* Set the credit limit (reset remaining credit to new limit). */ - netif->credit_bytes = netif->remaining_credit = creditlimit->credit_bytes; - netif->credit_usec = creditlimit->period_usec; + /* Set the credit limit (reset remaining credit to new limit). */ + netif->credit_bytes = creditlimit->credit_bytes; + netif->remaining_credit = creditlimit->credit_bytes; + netif->credit_usec = creditlimit->period_usec; - if (netif->status == CONNECTED) { - /* - * Schedule work so that any packets waiting under previous credit - * limit are dealt with (acts like a replenishment point). - */ - netif->credit_timeout.expires = jiffies; - netif_schedule_work(netif); - } + if (netif->status == CONNECTED) { + /* + * Schedule work so that any packets waiting under previous + * credit limit are dealt with (acts as a replenishment point). + */ + netif->credit_timeout.expires = jiffies; + netif_schedule_work(netif); + } #endif } int netif_disconnect(netif_t *netif) { - if (netif->status == CONNECTED) { - rtnl_lock(); - netif->status = DISCONNECTING; - wmb(); - if (netif_running(netif->dev)) - __netif_down(netif); - rtnl_unlock(); - netif_put(netif); - return 0; /* Caller should not send response message. */ - } + if (netif->status == CONNECTED) { + rtnl_lock(); + netif->status = DISCONNECTING; + wmb(); + if (netif_running(netif->dev)) + __netif_down(netif); + rtnl_unlock(); + netif_put(netif); + return 0; /* Caller should not send response message. */ + } - return 1; + return 1; } + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c index db948574bb..64fadba9de 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c @@ -57,8 +57,8 @@ static unsigned long mmap_vstart; #define PKT_PROT_LEN 64 static struct { - netif_tx_request_t req; - netif_t *netif; + 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; @@ -91,49 +91,49 @@ static spinlock_t mfn_lock = SPIN_LOCK_UNLOCKED; static unsigned long alloc_mfn(void) { - unsigned long mfn = 0, flags; - struct xen_memory_reservation reservation = { - .extent_start = mfn_list, - .nr_extents = MAX_MFN_ALLOC, - .extent_order = 0, - .domid = DOMID_SELF - }; - spin_lock_irqsave(&mfn_lock, flags); - if ( unlikely(alloc_index == 0) ) - alloc_index = HYPERVISOR_memory_op( - XENMEM_increase_reservation, &reservation); - if ( alloc_index != 0 ) - mfn = mfn_list[--alloc_index]; - spin_unlock_irqrestore(&mfn_lock, flags); - return mfn; + unsigned long mfn = 0, flags; + struct xen_memory_reservation reservation = { + .extent_start = mfn_list, + .nr_extents = MAX_MFN_ALLOC, + .extent_order = 0, + .domid = DOMID_SELF + }; + spin_lock_irqsave(&mfn_lock, flags); + if ( unlikely(alloc_index == 0) ) + alloc_index = HYPERVISOR_memory_op( + XENMEM_increase_reservation, &reservation); + if ( alloc_index != 0 ) + mfn = mfn_list[--alloc_index]; + spin_unlock_irqrestore(&mfn_lock, flags); + return mfn; } #ifndef CONFIG_XEN_NETDEV_GRANT static void free_mfn(unsigned long mfn) { - unsigned long flags; - struct xen_memory_reservation reservation = { - .extent_start = &mfn, - .nr_extents = 1, - .extent_order = 0, - .domid = DOMID_SELF - }; - spin_lock_irqsave(&mfn_lock, flags); - if ( alloc_index != MAX_MFN_ALLOC ) - mfn_list[alloc_index++] = mfn; - else if ( HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation) - != 1 ) - BUG(); - spin_unlock_irqrestore(&mfn_lock, flags); + unsigned long flags; + struct xen_memory_reservation reservation = { + .extent_start = &mfn, + .nr_extents = 1, + .extent_order = 0, + .domid = DOMID_SELF + }; + spin_lock_irqsave(&mfn_lock, flags); + if ( alloc_index != MAX_MFN_ALLOC ) + mfn_list[alloc_index++] = mfn; + else + BUG_ON(HYPERVISOR_memory_op(XENMEM_decrease_reservation, + &reservation) != 1); + spin_unlock_irqrestore(&mfn_lock, flags); } #endif 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); + smp_mb(); + if ((NR_PENDING_REQS < (MAX_PENDING_REQS/2)) && + !list_empty(&net_schedule_list)) + tasklet_schedule(&net_tx_tasklet); } /* @@ -142,77 +142,77 @@ static inline void maybe_schedule_tx_action(void) */ static inline int is_xen_skb(struct sk_buff *skb) { - extern kmem_cache_t *skbuff_cachep; - kmem_cache_t *cp = (kmem_cache_t *)virt_to_page(skb->head)->lru.next; - return (cp == skbuff_cachep); + extern kmem_cache_t *skbuff_cachep; + kmem_cache_t *cp = (kmem_cache_t *)virt_to_page(skb->head)->lru.next; + return (cp == skbuff_cachep); } int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev) { - netif_t *netif = netdev_priv(dev); + netif_t *netif = netdev_priv(dev); - ASSERT(skb->dev == dev); + ASSERT(skb->dev == dev); - /* Drop the packet if the target domain has no receive buffers. */ - if ( !netif->active || - (netif->rx_req_cons == netif->rx->req_prod) || - ((netif->rx_req_cons-netif->rx_resp_prod) == NETIF_RX_RING_SIZE) ) - goto drop; + /* Drop the packet if the target domain has no receive buffers. */ + if (!netif->active || + (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. The data is not allocated from our special cache. - * 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) || !is_xen_skb(skb) ) - { - int hlen = skb->data - skb->head; - struct sk_buff *nskb = dev_alloc_skb(hlen + skb->len); - if ( unlikely(nskb == NULL) ) - goto drop; - skb_reserve(nskb, hlen); - __skb_put(nskb, skb->len); - if (skb_copy_bits(skb, -hlen, nskb->data - hlen, skb->len + hlen)) - BUG(); - nskb->dev = skb->dev; - nskb->proto_csum_valid = skb->proto_csum_valid; - dev_kfree_skb(skb); - skb = nskb; - } + /* + * We do not copy the packet unless: + * 1. The data is shared; or + * 2. The data is not allocated from our special cache. + * 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) || !is_xen_skb(skb)) { + int hlen = skb->data - skb->head; + struct sk_buff *nskb = dev_alloc_skb(hlen + skb->len); + if ( unlikely(nskb == NULL) ) + goto drop; + skb_reserve(nskb, hlen); + __skb_put(nskb, skb->len); + BUG_ON(skb_copy_bits(skb, -hlen, nskb->data - hlen, + skb->len + hlen)); + nskb->dev = skb->dev; + nskb->proto_csum_valid = skb->proto_csum_valid; + dev_kfree_skb(skb); + skb = nskb; + } #ifdef CONFIG_XEN_NETDEV_GRANT #ifdef DEBUG_GRANT - printk(KERN_ALERT "#### be_xmit: req_prod=%d req_cons=%d id=%04x gr=%04x\n", - netif->rx->req_prod, - netif->rx_req_cons, - netif->rx->ring[ - MASK_NETIF_RX_IDX(netif->rx_req_cons)].req.id, - netif->rx->ring[ - MASK_NETIF_RX_IDX(netif->rx_req_cons)].req.gref); + printk(KERN_ALERT "#### be_xmit: req_prod=%d req_cons=%d " + "id=%04x gr=%04x\n", + netif->rx->req_prod, + netif->rx_req_cons, + netif->rx->ring[ + MASK_NETIF_RX_IDX(netif->rx_req_cons)].req.id, + netif->rx->ring[ + MASK_NETIF_RX_IDX(netif->rx_req_cons)].req.gref); #endif #endif - netif->rx_req_cons++; - netif_get(netif); + netif->rx_req_cons++; + netif_get(netif); - skb_queue_tail(&rx_queue, skb); - tasklet_schedule(&net_rx_tasklet); + skb_queue_tail(&rx_queue, skb); + tasklet_schedule(&net_rx_tasklet); - return 0; + return 0; drop: - netif->stats.tx_dropped++; - dev_kfree_skb(skb); - return 0; + netif->stats.tx_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); + 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): @@ -221,658 +221,654 @@ static void xen_network_done_notify(void) */ int xen_network_done(void) { - return skb_queue_empty(&rx_queue); + return skb_queue_empty(&rx_queue); } #endif static void net_rx_action(unsigned long unused) { - netif_t *netif = NULL; - s8 status; - u16 size, id, evtchn; - multicall_entry_t *mcl; - mmu_update_t *mmu; + netif_t *netif = NULL; + s8 status; + u16 size, id, evtchn; + multicall_entry_t *mcl; + mmu_update_t *mmu; #ifdef CONFIG_XEN_NETDEV_GRANT - gnttab_transfer_t *gop; + gnttab_transfer_t *gop; #else - struct mmuext_op *mmuext; + struct mmuext_op *mmuext; #endif - unsigned long vdata, old_mfn, new_mfn; - struct sk_buff_head rxq; - struct sk_buff *skb; - u16 notify_list[NETIF_RX_RING_SIZE]; - int notify_nr = 0; + unsigned long vdata, old_mfn, 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); + skb_queue_head_init(&rxq); - mcl = rx_mcl; - mmu = rx_mmu; + mcl = rx_mcl; + mmu = rx_mmu; #ifdef CONFIG_XEN_NETDEV_GRANT - gop = grant_rx_op; + gop = grant_rx_op; #else - mmuext = rx_mmuext; + mmuext = rx_mmuext; #endif - while ( (skb = skb_dequeue(&rx_queue)) != NULL ) - { - netif = netdev_priv(skb->dev); - vdata = (unsigned long)skb->data; - old_mfn = virt_to_mfn(vdata); + while ((skb = skb_dequeue(&rx_queue)) != NULL) { + netif = netdev_priv(skb->dev); + vdata = (unsigned long)skb->data; + old_mfn = virt_to_mfn(vdata); - /* Memory squeeze? Back off for an arbitrary while. */ - if ( (new_mfn = alloc_mfn()) == 0 ) - { - if ( net_ratelimit() ) - WPRINTK("Memory squeeze in netback driver.\n"); - mod_timer(&net_timer, jiffies + HZ); - skb_queue_head(&rx_queue, skb); - break; - } - /* - * Set the new P2M table entry before reassigning the old data page. - * Heed the comment in pgtable-2level.h:pte_page(). :-) - */ - phys_to_machine_mapping[__pa(skb->data) >> PAGE_SHIFT] = new_mfn; + /* Memory squeeze? Back off for an arbitrary while. */ + if ((new_mfn = alloc_mfn()) == 0) { + if ( net_ratelimit() ) + WPRINTK("Memory squeeze in netback driver.\n"); + mod_timer(&net_timer, jiffies + HZ); + skb_queue_head(&rx_queue, skb); + break; + } + /* + * Set the new P2M table entry before reassigning the old data + * page. Heed the comment in pgtable-2level.h:pte_page(). :-) + */ + phys_to_machine_mapping[__pa(skb->data) >> PAGE_SHIFT] = + new_mfn; - MULTI_update_va_mapping(mcl, vdata, - pfn_pte_ma(new_mfn, PAGE_KERNEL), 0); - mcl++; + MULTI_update_va_mapping(mcl, vdata, + pfn_pte_ma(new_mfn, PAGE_KERNEL), 0); + mcl++; #ifdef CONFIG_XEN_NETDEV_GRANT - gop->mfn = old_mfn; - gop->domid = netif->domid; - gop->ref = netif->rx->ring[ - MASK_NETIF_RX_IDX(netif->rx_resp_prod_copy)].req.gref; - netif->rx_resp_prod_copy++; - gop++; + gop->mfn = old_mfn; + gop->domid = netif->domid; + gop->ref = netif->rx->ring[ + MASK_NETIF_RX_IDX(netif->rx_resp_prod_copy)].req.gref; + netif->rx_resp_prod_copy++; + gop++; #else - mcl->op = __HYPERVISOR_mmuext_op; - mcl->args[0] = (unsigned long)mmuext; - mcl->args[1] = 1; - mcl->args[2] = 0; - mcl->args[3] = netif->domid; - mcl++; + mcl->op = __HYPERVISOR_mmuext_op; + mcl->args[0] = (unsigned long)mmuext; + mcl->args[1] = 1; + mcl->args[2] = 0; + mcl->args[3] = netif->domid; + mcl++; - mmuext->cmd = MMUEXT_REASSIGN_PAGE; - mmuext->arg1.mfn = old_mfn; - mmuext++; + mmuext->cmd = MMUEXT_REASSIGN_PAGE; + mmuext->arg1.mfn = old_mfn; + mmuext++; #endif - mmu->ptr = ((unsigned long long)new_mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE; - mmu->val = __pa(vdata) >> PAGE_SHIFT; - mmu++; + mmu->ptr = ((maddr_t)new_mfn << PAGE_SHIFT) | + MMU_MACHPHYS_UPDATE; + mmu->val = __pa(vdata) >> PAGE_SHIFT; + mmu++; - __skb_queue_tail(&rxq, skb); + __skb_queue_tail(&rxq, skb); #ifdef DEBUG_GRANT - dump_packet('a', old_mfn, vdata); + dump_packet('a', old_mfn, vdata); #endif - /* Filled the batch queue? */ - if ( (mcl - rx_mcl) == ARRAY_SIZE(rx_mcl) ) - break; - } + /* Filled the batch queue? */ + if ((mcl - rx_mcl) == ARRAY_SIZE(rx_mcl)) + break; + } - if ( mcl == rx_mcl ) - return; + if (mcl == rx_mcl) + return; - mcl->op = __HYPERVISOR_mmu_update; - mcl->args[0] = (unsigned long)rx_mmu; - mcl->args[1] = mmu - rx_mmu; - mcl->args[2] = 0; - mcl->args[3] = DOMID_SELF; - mcl++; + mcl->op = __HYPERVISOR_mmu_update; + mcl->args[0] = (unsigned long)rx_mmu; + mcl->args[1] = mmu - rx_mmu; + mcl->args[2] = 0; + mcl->args[3] = DOMID_SELF; + mcl++; #ifdef CONFIG_XEN_NETDEV_GRANT - mcl[-2].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL; + mcl[-2].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL; #else - mcl[-3].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL; + mcl[-3].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL; #endif - if ( unlikely(HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl) != 0) ) - BUG(); + BUG_ON(HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl) != 0); - mcl = rx_mcl; + mcl = rx_mcl; #ifdef CONFIG_XEN_NETDEV_GRANT - if(HYPERVISOR_grant_table_op(GNTTABOP_transfer, grant_rx_op, - gop - grant_rx_op)) { - /* - ** The other side has given us a bad grant ref, or has no headroom, - ** or has gone away. Unfortunately the current grant table code - ** doesn't inform us which is the case, so not much we can do. - */ - DPRINTK("net_rx: transfer to DOM%u failed; dropping (up to) %d " - "packets.\n", grant_rx_op[0].domid, gop - grant_rx_op); - } - gop = grant_rx_op; + if(HYPERVISOR_grant_table_op(GNTTABOP_transfer, grant_rx_op, + gop - grant_rx_op)) { + /* + * The other side has given us a bad grant ref, or has no + * headroom, or has gone away. Unfortunately the current grant + * table code doesn't inform us which is the case, so not much + * we can do. + */ + DPRINTK("net_rx: transfer to DOM%u failed; dropping (up to) " + "%d packets.\n", + grant_rx_op[0].domid, gop - grant_rx_op); + } + gop = grant_rx_op; #else - mmuext = rx_mmuext; + mmuext = rx_mmuext; #endif - while ( (skb = __skb_dequeue(&rxq)) != NULL ) - { - netif = netdev_priv(skb->dev); - size = skb->tail - skb->data; + while ((skb = __skb_dequeue(&rxq)) != NULL) { + netif = netdev_priv(skb->dev); + size = skb->tail - skb->data; - /* Rederive the machine addresses. */ - new_mfn = mcl[0].args[1] >> PAGE_SHIFT; + /* Rederive the machine addresses. */ + new_mfn = mcl[0].args[1] >> PAGE_SHIFT; #ifdef CONFIG_XEN_NETDEV_GRANT - old_mfn = 0; /* XXX Fix this so we can free_mfn() on error! */ + old_mfn = 0; /* XXX Fix this so we can free_mfn() on error! */ #else - old_mfn = mmuext[0].arg1.mfn; + old_mfn = mmuext[0].arg1.mfn; #endif - atomic_set(&(skb_shinfo(skb)->dataref), 1); - skb_shinfo(skb)->nr_frags = 0; - skb_shinfo(skb)->frag_list = NULL; + atomic_set(&(skb_shinfo(skb)->dataref), 1); + skb_shinfo(skb)->nr_frags = 0; + skb_shinfo(skb)->frag_list = NULL; - netif->stats.tx_bytes += size; - netif->stats.tx_packets++; + netif->stats.tx_bytes += size; + netif->stats.tx_packets++; - /* The update_va_mapping() must not fail. */ - BUG_ON(mcl[0].result != 0); + /* The update_va_mapping() must not fail. */ + BUG_ON(mcl[0].result != 0); - /* Check the reassignment error code. */ - status = NETIF_RSP_OKAY; + /* Check the reassignment error code. */ + status = NETIF_RSP_OKAY; #ifdef CONFIG_XEN_NETDEV_GRANT - if(gop->status != 0) { - DPRINTK("Bad status %d from grant transfer to DOM%u\n", - gop->status, netif->domid); - /* XXX SMH: should free 'old_mfn' here */ - status = NETIF_RSP_ERROR; - } + if(gop->status != 0) { + DPRINTK("Bad status %d from grant transfer to DOM%u\n", + gop->status, netif->domid); + /* XXX SMH: should free 'old_mfn' here */ + status = NETIF_RSP_ERROR; + } #else - if ( unlikely(mcl[1].result != 0) ) - { - DPRINTK("Failed MMU update transferring to DOM%u\n", netif->domid); - free_mfn(old_mfn); - status = NETIF_RSP_ERROR; - } + if (unlikely(mcl[1].result != 0)) { + DPRINTK("Failed MMU update transferring to DOM%u\n", + netif->domid); + free_mfn(old_mfn); + status = NETIF_RSP_ERROR; + } #endif - evtchn = netif->evtchn; - id = netif->rx->ring[MASK_NETIF_RX_IDX(netif->rx_resp_prod)].req.id; - if ( make_rx_response(netif, id, status, - (old_mfn << PAGE_SHIFT) | /* XXX */ - ((unsigned long)skb->data & ~PAGE_MASK), - size, skb->proto_csum_valid) && - (rx_notify[evtchn] == 0) ) - { - rx_notify[evtchn] = 1; - notify_list[notify_nr++] = evtchn; - } + evtchn = netif->evtchn; + id = netif->rx->ring[ + MASK_NETIF_RX_IDX(netif->rx_resp_prod)].req.id; + if (make_rx_response(netif, id, status, + (old_mfn << PAGE_SHIFT) | /* XXX */ + ((unsigned long)skb->data & ~PAGE_MASK), + size, skb->proto_csum_valid) && + (rx_notify[evtchn] == 0)) { + rx_notify[evtchn] = 1; + notify_list[notify_nr++] = evtchn; + } - netif_put(netif); - dev_kfree_skb(skb); + netif_put(netif); + dev_kfree_skb(skb); #ifdef CONFIG_XEN_NETDEV_GRANT - mcl++; - gop++; + mcl++; + gop++; #else - mcl += 2; - mmuext += 1; + mcl += 2; + mmuext += 1; #endif - } + } - while ( notify_nr != 0 ) - { - evtchn = notify_list[--notify_nr]; - rx_notify[evtchn] = 0; - notify_via_evtchn(evtchn); - } + while (notify_nr != 0) { + evtchn = notify_list[--notify_nr]; + rx_notify[evtchn] = 0; + notify_via_evtchn(evtchn); + } - out: - /* More work to do? */ - if ( !skb_queue_empty(&rx_queue) && !timer_pending(&net_timer) ) - tasklet_schedule(&net_rx_tasklet); + /* More work to do? */ + if (!skb_queue_empty(&rx_queue) && !timer_pending(&net_timer)) + tasklet_schedule(&net_rx_tasklet); #if 0 - else - xen_network_done_notify(); + else + xen_network_done_notify(); #endif } static void net_alarm(unsigned long unused) { - tasklet_schedule(&net_rx_tasklet); + tasklet_schedule(&net_rx_tasklet); } struct net_device_stats *netif_be_get_stats(struct net_device *dev) { - netif_t *netif = netdev_priv(dev); - return &netif->stats; + netif_t *netif = netdev_priv(dev); + return &netif->stats; } static int __on_net_schedule_list(netif_t *netif) { - return netif->list.next != NULL; + 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); + 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; + if (__on_net_schedule_list(netif)) + return; - spin_lock_irq(&net_schedule_list_lock); - if ( !__on_net_schedule_list(netif) && netif->active ) - { - list_add_tail(&netif->list, &net_schedule_list); - netif_get(netif); - } - spin_unlock_irq(&net_schedule_list_lock); + spin_lock_irq(&net_schedule_list_lock); + if (!__on_net_schedule_list(netif) && netif->active) { + list_add_tail(&netif->list, &net_schedule_list); + netif_get(netif); + } + spin_unlock_irq(&net_schedule_list_lock); } 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(); - } + 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_work(netif_t *netif) { - remove_from_net_schedule_list(netif); + remove_from_net_schedule_list(netif); } static void tx_credit_callback(unsigned long data) { - netif_t *netif = (netif_t *)data; - netif->remaining_credit = netif->credit_bytes; - netif_schedule_work(netif); + netif_t *netif = (netif_t *)data; + netif->remaining_credit = netif->credit_bytes; + netif_schedule_work(netif); } inline static void net_tx_action_dealloc(void) { #ifdef CONFIG_XEN_NETDEV_GRANT - gnttab_unmap_grant_ref_t *gop; + gnttab_unmap_grant_ref_t *gop; #else - multicall_entry_t *mcl; + multicall_entry_t *mcl; #endif - u16 pending_idx; - PEND_RING_IDX dc, dp; - netif_t *netif; + u16 pending_idx; + PEND_RING_IDX dc, dp; + netif_t *netif; - dc = dealloc_cons; - dp = dealloc_prod; + dc = dealloc_cons; + dp = dealloc_prod; #ifdef CONFIG_XEN_NETDEV_GRANT - /* - * Free up any grants we have finished using - */ - gop = tx_unmap_ops; - while ( dc != dp ) - { - pending_idx = dealloc_ring[MASK_PEND_IDX(dc++)]; - gop->host_addr = MMAP_VADDR(pending_idx); - gop->dev_bus_addr = 0; - gop->handle = grant_tx_ref[pending_idx]; - grant_tx_ref[pending_idx] = GRANT_INVALID_REF; - gop++; - } - BUG_ON(HYPERVISOR_grant_table_op( - GNTTABOP_unmap_grant_ref, tx_unmap_ops, gop - tx_unmap_ops)); + /* + * Free up any grants we have finished using + */ + gop = tx_unmap_ops; + while (dc != dp) { + pending_idx = dealloc_ring[MASK_PEND_IDX(dc++)]; + gop->host_addr = MMAP_VADDR(pending_idx); + gop->dev_bus_addr = 0; + gop->handle = grant_tx_ref[pending_idx]; + grant_tx_ref[pending_idx] = GRANT_INVALID_REF; + gop++; + } + BUG_ON(HYPERVISOR_grant_table_op( + GNTTABOP_unmap_grant_ref, tx_unmap_ops, gop - tx_unmap_ops)); #else - mcl = tx_mcl; - while ( dc != dp ) - { - pending_idx = dealloc_ring[MASK_PEND_IDX(dc++)]; - MULTI_update_va_mapping(mcl, MMAP_VADDR(pending_idx), - __pte(0), 0); - mcl++; - } + mcl = tx_mcl; + while (dc != dp) { + pending_idx = dealloc_ring[MASK_PEND_IDX(dc++)]; + MULTI_update_va_mapping(mcl, MMAP_VADDR(pending_idx), + __pte(0), 0); + mcl++; + } - mcl[-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL; - if ( unlikely(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0) ) - BUG(); + mcl[-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL; + BUG_ON(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0); - mcl = tx_mcl; + mcl = tx_mcl; #endif - while ( dealloc_cons != dp ) - { + while (dealloc_cons != dp) { #ifndef CONFIG_XEN_NETDEV_GRANT - /* The update_va_mapping() must not fail. */ - BUG_ON(mcl[0].result != 0); + /* The update_va_mapping() must not fail. */ + BUG_ON(mcl[0].result != 0); #endif - pending_idx = dealloc_ring[MASK_PEND_IDX(dealloc_cons++)]; + pending_idx = dealloc_ring[MASK_PEND_IDX(dealloc_cons++)]; - netif = pending_tx_info[pending_idx].netif; + netif = pending_tx_info[pending_idx].netif; - make_tx_response(netif, pending_tx_info[pending_idx].req.id, - NETIF_RSP_OKAY); + make_tx_response(netif, pending_tx_info[pending_idx].req.id, + NETIF_RSP_OKAY); - pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx; + 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 if that - * guest is testing against 'resp_prod' when deciding whether to notify - * us when it queues additional packets. - */ - 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); + /* + * Scheduling checks must happen after the above response is + * posted. This avoids a possible race with a guest OS on + * another CPU if that guest is testing against 'resp_prod' + * when deciding whether to notify us when it queues additional + * packets. + */ + 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); + netif_put(netif); #ifndef CONFIG_XEN_NETDEV_GRANT - mcl++; + mcl++; #endif - } - + } } /* Called after netfront has transmitted */ 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 list_head *ent; + struct sk_buff *skb; + netif_t *netif; + netif_tx_request_t txreq; + u16 pending_idx; + NETIF_RING_IDX i; #ifdef CONFIG_XEN_NETDEV_GRANT - gnttab_map_grant_ref_t *mop; + gnttab_map_grant_ref_t *mop; #else - multicall_entry_t *mcl; + multicall_entry_t *mcl; #endif - unsigned int data_len; + unsigned int data_len; - if ( dealloc_cons != dealloc_prod ) - net_tx_action_dealloc(); + if (dealloc_cons != dealloc_prod) + net_tx_action_dealloc(); #ifdef CONFIG_XEN_NETDEV_GRANT - mop = tx_map_ops; + mop = tx_map_ops; #else - mcl = tx_mcl; + mcl = tx_mcl; #endif - 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); + 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; - } + /* 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; + } - rmb(); /* Ensure that we see the request before we copy it. */ - memcpy(&txreq, &netif->tx->ring[MASK_NETIF_TX_IDX(i)].req, - sizeof(txreq)); - /* Credit-based scheduling. */ - if ( txreq.size > netif->remaining_credit ) - { - unsigned long now = jiffies; - unsigned long next_credit = - netif->credit_timeout.expires + - msecs_to_jiffies(netif->credit_usec / 1000); + rmb(); /* Ensure that we see the request before we copy it. */ + memcpy(&txreq, &netif->tx->ring[MASK_NETIF_TX_IDX(i)].req, + sizeof(txreq)); + /* Credit-based scheduling. */ + if (txreq.size > netif->remaining_credit) { + unsigned long now = jiffies; + unsigned long next_credit = + netif->credit_timeout.expires + + msecs_to_jiffies(netif->credit_usec / 1000); - /* Timer could already be pending in some rare cases. */ - if ( timer_pending(&netif->credit_timeout) ) - break; + /* Timer could already be pending in rare cases. */ + if (timer_pending(&netif->credit_timeout)) + break; - /* Already passed the point at which we can replenish credit? */ - if ( time_after_eq(now, next_credit) ) - { - netif->credit_timeout.expires = now; - netif->remaining_credit = netif->credit_bytes; - } + /* Passed the point where we can replenish credit? */ + if (time_after_eq(now, next_credit)) { + netif->credit_timeout.expires = now; + netif->remaining_credit = netif->credit_bytes; + } - /* Still too big to send right now? Then set a timer callback. */ - if ( txreq.size > netif->remaining_credit ) - { - netif->remaining_credit = 0; - netif->credit_timeout.expires = next_credit; - netif->credit_timeout.data = (unsigned long)netif; - netif->credit_timeout.function = tx_credit_callback; - add_timer_on(&netif->credit_timeout, smp_processor_id()); - break; - } - } - netif->remaining_credit -= txreq.size; + /* Still too big to send right now? Set a callback. */ + if (txreq.size > netif->remaining_credit) { + netif->remaining_credit = 0; + netif->credit_timeout.expires = + next_credit; + netif->credit_timeout.data = + (unsigned long)netif; + netif->credit_timeout.function = + tx_credit_callback; + add_timer_on(&netif->credit_timeout, + smp_processor_id()); + break; + } + } + netif->remaining_credit -= txreq.size; - /* - * Why the barrier? It ensures that the frontend sees updated req_cons - * before we check for more work to schedule. - */ - netif->tx->req_cons = ++netif->tx_req_cons; - mb(); + /* + * Why the barrier? It ensures that the frontend sees updated + * req_cons before we check for more work to schedule. + */ + netif->tx->req_cons = ++netif->tx_req_cons; + mb(); - netif_schedule_work(netif); + netif_schedule_work(netif); - if ( unlikely(txreq.size < ETH_HLEN) || - 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; - } + if (unlikely(txreq.size < ETH_HLEN) || + 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; - } + /* No crossing a page 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)]; + pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)]; - data_len = (txreq.size > PKT_PROT_LEN) ? PKT_PROT_LEN : txreq.size; + data_len = (txreq.size > PKT_PROT_LEN) ? + PKT_PROT_LEN : txreq.size; - if ( unlikely((skb = alloc_skb(data_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; - } + skb = alloc_skb(data_len+16, GFP_ATOMIC); + if (unlikely(skb == 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); + /* Packets passed to netif_rx() must have some headroom. */ + skb_reserve(skb, 16); #ifdef CONFIG_XEN_NETDEV_GRANT - mop->host_addr = MMAP_VADDR(pending_idx); - mop->dom = netif->domid; - mop->ref = txreq.addr >> PAGE_SHIFT; - mop->flags = GNTMAP_host_map | GNTMAP_readonly; - mop++; + mop->host_addr = MMAP_VADDR(pending_idx); + mop->dom = netif->domid; + mop->ref = txreq.addr >> PAGE_SHIFT; + mop->flags = GNTMAP_host_map | GNTMAP_readonly; + mop++; #else - MULTI_update_va_mapping_otherdomain( - mcl, MMAP_VADDR(pending_idx), - pfn_pte_ma(txreq.addr >> PAGE_SHIFT, PAGE_KERNEL), - 0, netif->domid); + MULTI_update_va_mapping_otherdomain( + mcl, MMAP_VADDR(pending_idx), + pfn_pte_ma(txreq.addr >> PAGE_SHIFT, PAGE_KERNEL), + 0, netif->domid); - mcl++; + mcl++; #endif - memcpy(&pending_tx_info[pending_idx].req, &txreq, sizeof(txreq)); - pending_tx_info[pending_idx].netif = netif; - *((u16 *)skb->data) = pending_idx; + 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); + __skb_queue_tail(&tx_queue, skb); - pending_cons++; + pending_cons++; #ifdef CONFIG_XEN_NETDEV_GRANT - if ( (mop - tx_map_ops) >= ARRAY_SIZE(tx_map_ops) ) - break; + if ((mop - tx_map_ops) >= ARRAY_SIZE(tx_map_ops)) + break; #else - /* Filled the batch queue? */ - if ( (mcl - tx_mcl) == ARRAY_SIZE(tx_mcl) ) - break; + /* Filled the batch queue? */ + if ((mcl - tx_mcl) == ARRAY_SIZE(tx_mcl)) + break; #endif - } + } #ifdef CONFIG_XEN_NETDEV_GRANT - if ( mop == tx_map_ops ) - return; + if (mop == tx_map_ops) + return; - BUG_ON(HYPERVISOR_grant_table_op( - GNTTABOP_map_grant_ref, tx_map_ops, mop - tx_map_ops)); + BUG_ON(HYPERVISOR_grant_table_op( + GNTTABOP_map_grant_ref, tx_map_ops, mop - tx_map_ops)); - mop = tx_map_ops; + mop = tx_map_ops; #else - if ( mcl == tx_mcl ) - return; + if (mcl == tx_mcl) + return; - BUG_ON(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0); + BUG_ON(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0); - mcl = tx_mcl; + mcl = tx_mcl; #endif - 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)); + 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. */ + /* Check the remap error code. */ #ifdef CONFIG_XEN_NETDEV_GRANT - if ( unlikely(mop->handle < 0) ) - { - printk(KERN_ALERT "#### netback grant fails\n"); - make_tx_response(netif, txreq.id, NETIF_RSP_ERROR); - netif_put(netif); - kfree_skb(skb); - mop++; - pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx; - continue; - } - phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT] = - FOREIGN_FRAME(mop->dev_bus_addr >> PAGE_SHIFT); - grant_tx_ref[pending_idx] = mop->handle; + if (unlikely(mop->handle < 0)) { + printk(KERN_ALERT "#### netback grant fails\n"); + make_tx_response(netif, txreq.id, NETIF_RSP_ERROR); + netif_put(netif); + kfree_skb(skb); + mop++; + pending_ring[MASK_PEND_IDX(pending_prod++)] = + pending_idx; + continue; + } + phys_to_machine_mapping[ + __pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT] = + FOREIGN_FRAME(mop->dev_bus_addr >> PAGE_SHIFT); + grant_tx_ref[pending_idx] = mop->handle; #else - if ( unlikely(mcl[0].result != 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; - } + if (unlikely(mcl[0].result != 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] = - FOREIGN_FRAME(txreq.addr >> PAGE_SHIFT); + phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx)) >> + PAGE_SHIFT] = + FOREIGN_FRAME(txreq.addr >> PAGE_SHIFT); #endif - data_len = (txreq.size > PKT_PROT_LEN) ? PKT_PROT_LEN : txreq.size; + data_len = (txreq.size > PKT_PROT_LEN) ? + PKT_PROT_LEN : txreq.size; - __skb_put(skb, data_len); - memcpy(skb->data, - (void *)(MMAP_VADDR(pending_idx)|(txreq.addr&~PAGE_MASK)), - data_len); - if ( data_len < txreq.size ) - { - /* Append the packet payload as a fragment. */ - skb_shinfo(skb)->frags[0].page = - virt_to_page(MMAP_VADDR(pending_idx)); - skb_shinfo(skb)->frags[0].size = txreq.size - data_len; - skb_shinfo(skb)->frags[0].page_offset = - (txreq.addr + data_len) & ~PAGE_MASK; - skb_shinfo(skb)->nr_frags = 1; - } - else - { - /* Schedule a response immediately. */ - netif_idx_release(pending_idx); - } + __skb_put(skb, data_len); + memcpy(skb->data, + (void *)(MMAP_VADDR(pending_idx)| + (txreq.addr&~PAGE_MASK)), + data_len); + if (data_len < txreq.size) { + /* Append the packet payload as a fragment. */ + skb_shinfo(skb)->frags[0].page = + virt_to_page(MMAP_VADDR(pending_idx)); + skb_shinfo(skb)->frags[0].size = + txreq.size - data_len; + skb_shinfo(skb)->frags[0].page_offset = + (txreq.addr + data_len) & ~PAGE_MASK; + skb_shinfo(skb)->nr_frags = 1; + } else { + /* Schedule a response immediately. */ + netif_idx_release(pending_idx); + } - skb->data_len = txreq.size - data_len; - skb->len += skb->data_len; + skb->data_len = txreq.size - data_len; + skb->len += skb->data_len; - skb->dev = netif->dev; - skb->protocol = eth_type_trans(skb, skb->dev); + skb->dev = netif->dev; + skb->protocol = eth_type_trans(skb, skb->dev); - /* No checking needed on localhost, but remember the field is blank. */ - skb->ip_summed = CHECKSUM_UNNECESSARY; - skb->proto_csum_valid = 1; - skb->proto_csum_blank = txreq.csum_blank; + /* + * No checking needed on localhost, but remember the field is + * blank. + */ + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->proto_csum_valid = 1; + skb->proto_csum_blank = txreq.csum_blank; - netif->stats.rx_bytes += txreq.size; - netif->stats.rx_packets++; + netif->stats.rx_bytes += txreq.size; + netif->stats.rx_packets++; - netif_rx(skb); - netif->dev->last_rx = jiffies; + netif_rx(skb); + netif->dev->last_rx = jiffies; #ifdef CONFIG_XEN_NETDEV_GRANT - mop++; + mop++; #else - mcl++; + mcl++; #endif - } + } } static void netif_idx_release(u16 pending_idx) { - static spinlock_t _lock = SPIN_LOCK_UNLOCKED; - unsigned long flags; + static spinlock_t _lock = SPIN_LOCK_UNLOCKED; + unsigned long flags; - spin_lock_irqsave(&_lock, flags); - dealloc_ring[MASK_PEND_IDX(dealloc_prod++)] = pending_idx; - spin_unlock_irqrestore(&_lock, flags); + spin_lock_irqsave(&_lock, flags); + dealloc_ring[MASK_PEND_IDX(dealloc_prod++)] = pending_idx; + spin_unlock_irqrestore(&_lock, flags); - tasklet_schedule(&net_tx_tasklet); + tasklet_schedule(&net_tx_tasklet); } static void netif_page_release(struct page *page) { - u16 pending_idx = page - virt_to_page(mmap_vstart); + u16 pending_idx = page - virt_to_page(mmap_vstart); - /* Ready for next use. */ - set_page_count(page, 1); + /* Ready for next use. */ + set_page_count(page, 1); - netif_idx_release(pending_idx); + netif_idx_release(pending_idx); } irqreturn_t 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(); - } - return IRQ_HANDLED; + netif_t *netif = dev_id; + if (tx_work_exists(netif)) { + add_to_net_schedule_list_tail(netif); + maybe_schedule_tx_action(); + } + return IRQ_HANDLED; } 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; + 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; + 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); + 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, @@ -882,110 +878,120 @@ static int make_rx_response(netif_t *netif, u16 size, u16 csum_valid) { - NETIF_RING_IDX i = netif->rx_resp_prod; - netif_rx_response_t *resp; + 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->csum_valid = csum_valid; - resp->id = id; - resp->status = (s16)size; - if ( st < 0 ) - resp->status = (s16)st; - wmb(); - netif->rx->resp_prod = netif->rx_resp_prod = ++i; + resp = &netif->rx->ring[MASK_NETIF_RX_IDX(i)].resp; + resp->addr = addr; + resp->csum_valid = csum_valid; + 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); + mb(); /* Update producer before checking event threshold. */ + return (i == netif->rx->event); } static irqreturn_t netif_be_dbg(int irq, void *dev_id, struct pt_regs *regs) { - struct list_head *ent; - netif_t *netif; - int i = 0; + struct list_head *ent; + netif_t *netif; + int i = 0; - printk(KERN_ALERT "netif_schedule_list:\n"); - spin_lock_irq(&net_schedule_list_lock); + 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++; - } + 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"); + spin_unlock_irq(&net_schedule_list_lock); + printk(KERN_ALERT " ** End of netif_schedule_list **\n"); - return IRQ_HANDLED; + return IRQ_HANDLED; } static int __init netback_init(void) { - int i; - struct page *page; + int i; + struct page *page; - if ( !(xen_start_info->flags & SIF_NET_BE_DOMAIN) && - !(xen_start_info->flags & SIF_INITDOMAIN) ) - return 0; + if (!(xen_start_info->flags & SIF_NET_BE_DOMAIN) && + !(xen_start_info->flags & SIF_INITDOMAIN)) + return 0; - IPRINTK("Initialising Xen netif backend.\n"); + IPRINTK("Initialising Xen netif backend.\n"); #ifdef CONFIG_XEN_NETDEV_GRANT - IPRINTK("Using grant tables.\n"); + IPRINTK("Using grant tables.\n"); #endif - /* We can increase reservation by this much in net_rx_action(). */ - balloon_update_driver_allowance(NETIF_RX_RING_SIZE); + /* We can increase reservation by this much in net_rx_action(). */ + balloon_update_driver_allowance(NETIF_RX_RING_SIZE); - skb_queue_head_init(&rx_queue); - skb_queue_head_init(&tx_queue); + skb_queue_head_init(&rx_queue); + skb_queue_head_init(&tx_queue); - init_timer(&net_timer); - net_timer.data = 0; - net_timer.function = net_alarm; + init_timer(&net_timer); + net_timer.data = 0; + net_timer.function = net_alarm; - page = balloon_alloc_empty_page_range(MAX_PENDING_REQS); - BUG_ON(page == NULL); - mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page)); + page = balloon_alloc_empty_page_range(MAX_PENDING_REQS); + BUG_ON(page == NULL); + mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page)); - for ( i = 0; i < MAX_PENDING_REQS; i++ ) - { - page = virt_to_page(MMAP_VADDR(i)); - set_page_count(page, 1); - SetPageForeign(page, netif_page_release); - } + for (i = 0; i < MAX_PENDING_REQS; i++) { + page = virt_to_page(MMAP_VADDR(i)); + set_page_count(page, 1); + SetPageForeign(page, netif_page_release); + } - pending_cons = 0; - pending_prod = MAX_PENDING_REQS; - for ( i = 0; i < MAX_PENDING_REQS; i++ ) - pending_ring[i] = i; + 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); + spin_lock_init(&net_schedule_list_lock); + INIT_LIST_HEAD(&net_schedule_list); - netif_xenbus_init(); + netif_xenbus_init(); - (void)request_irq(bind_virq_to_irq(VIRQ_DEBUG), - netif_be_dbg, SA_SHIRQ, - "net-be-dbg", &netif_be_dbg); + (void)request_irq(bind_virq_to_irq(VIRQ_DEBUG), + netif_be_dbg, SA_SHIRQ, + "net-be-dbg", &netif_be_dbg); - return 0; + return 0; } static void netback_cleanup(void) { - BUG(); + BUG(); } module_init(netback_init); module_exit(netback_cleanup); + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c index 80050f9c18..d5a41728f7 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c @@ -294,3 +294,13 @@ void netif_xenbus_init(void) { xenbus_register_backend(&netback); } + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */