[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] merge?
# HG changeset patch # User cl349@xxxxxxxxxxxxxxxxxxxx # Node ID ffbc98d735bdb058a8cff968980ea276eddce146 # Parent 7cccdb49af7537b42b0df1d879713957a4bc51b0 # Parent 7fbaf67a0af5048f94640ea0e44b88408b21b791 merge? diff -r 7cccdb49af75 -r ffbc98d735bd linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c Fri Sep 16 18:06:42 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c Fri Sep 16 18:07:50 2005 @@ -45,12 +45,12 @@ 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 @@ 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 @@ #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 -r 7cccdb49af75 -r ffbc98d735bd linux-2.6-xen-sparse/arch/xen/i386/pci/i386.c --- a/linux-2.6-xen-sparse/arch/xen/i386/pci/i386.c Fri Sep 16 18:06:42 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/pci/i386.c Fri Sep 16 18:07:50 2005 @@ -295,7 +295,7 @@ /* 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 -r 7cccdb49af75 -r ffbc98d735bd linux-2.6-xen-sparse/arch/xen/kernel/devmem.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/devmem.c Fri Sep 16 18:06:42 2005 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/devmem.c Fri Sep 16 18:07:50 2005 @@ -90,22 +90,10 @@ 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 -r 7cccdb49af75 -r ffbc98d735bd linux-2.6-xen-sparse/drivers/xen/netback/common.h --- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h Fri Sep 16 18:06:42 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h Fri Sep 16 18:07:50 2005 @@ -18,16 +18,10 @@ #include <asm-xen/xen-public/io/netif.h> #include <asm/io.h> #include <asm/pgalloc.h> - -#ifdef CONFIG_XEN_NETDEV_GRANT #include <asm-xen/xen-public/grant_table.h> #include <asm-xen/gnttab.h> #define GRANT_INVALID_REF (0xFFFF) - -#endif - - #if 0 #define ASSERT(_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; -typedef struct netif_st { - /* 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; +#ifdef CONFIG_XEN_NETDEV_GRANT + u16 tx_shmem_handle; + unsigned long tx_shmem_vaddr; + grant_ref_t tx_shmem_ref; +#endif + 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; +#endif + unsigned int evtchn; + unsigned int remote_evtchn; - /* Physical parameters of the comms window. */ - unsigned long tx_shmem_frame; + /* 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 */ #ifdef CONFIG_XEN_NETDEV_GRANT - u16 tx_shmem_handle; - unsigned long tx_shmem_vaddr; - grant_ref_t tx_shmem_ref; + NETIF_RING_IDX rx_resp_prod_copy; #endif - 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; -#endif - unsigned int evtchn; - unsigned int remote_evtchn; + NETIF_RING_IDX tx_req_cons; + NETIF_RING_IDX tx_resp_prod; /* private version of shared variable */ - /* The shared rings and indexes. */ - netif_tx_interface_t *tx; - netif_rx_interface_t *rx; + /* 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; - /* 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 */ -#endif - NETIF_RING_IDX tx_req_cons; - NETIF_RING_IDX tx_resp_prod; /* private version of shared variable */ + /* 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; - /* 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; - - 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 @@ 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 -r 7cccdb49af75 -r ffbc98d735bd linux-2.6-xen-sparse/drivers/xen/netback/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Fri Sep 16 18:06:42 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Fri Sep 16 18:07:50 2005 @@ -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] = {}; - - 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->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; - - /* 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); - - 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; + 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; + } + + 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); + + 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; + + 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; + } + + DPRINTK("Successfully created netif\n"); + return netif; } static int map_frontend_pages(netif_t *netif, unsigned long localaddr, @@ -116,191 +117,204 @@ unsigned long rx_ring_ref) { #ifdef CONFIG_XEN_NETDEV_GRANT - 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; + struct gnttab_map_grant_ref op; + + /* Map: Use the Grant table reference */ + op.host_addr = localaddr; + op.flags = GNTMAP_host_map; + op.ref = tx_ring_ref; + op.dom = netif->domid; - BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) ); - if (op.handle < 0) { - DPRINTK(" Grant table operation failure 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; - - /* 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; - } - - netif->rx_shmem_ref = rx_ring_ref; - netif->rx_shmem_handle = op.handle; - netif->rx_shmem_vaddr = localaddr + PAGE_SIZE; + 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; + + /* 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(" 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; #else - pgprot_t prot = __pgprot(_KERNPG_TABLE); - int err; - - err = direct_remap_pfn_range(&init_mm, localaddr, - tx_ring_ref, PAGE_SIZE, - prot, netif->domid); + 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 + PAGE_SIZE, - rx_ring_ref, PAGE_SIZE, - prot, netif->domid); - - if (err) - return err; + err |= direct_remap_pfn_range( + &init_mm, localaddr + PAGE_SIZE, + rx_ring_ref, PAGE_SIZE, + prot, netif->domid); + + 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; - - 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)); + 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->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; - - 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; - } - - 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->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(); - - return 0; -} - -static void free_netif(void *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. - */ - - 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); - - if (netif->tx) { - unmap_frontend_pages(netif); - vfree(netif->tx); /* Frees netif->rx as well. */ - } - - free_netdev(netif->dev); -} - -void free_netif_callback(netif_t *netif) -{ - INIT_WORK(&netif->free_work, free_netif, (void *)netif); - schedule_work(&netif->free_work); + 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; + + 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; + } + + 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. */ + + rtnl_lock(); + netif->status = CONNECTED; + wmb(); + if (netif_running(netif->dev)) + __netif_up(netif); + rtnl_unlock(); + + return 0; +} + +static void free_netif_callback(void *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. + */ + + 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); + + if (netif->tx) { + unmap_frontend_pages(netif); + vfree(netif->tx); /* Frees netif->rx as well. */ + } + + free_netdev(netif->dev); +} + +void free_netif(netif_t *netif) +{ + 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; - - 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); - } + /* 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 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. */ - } - - return 1; -} + 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; +} + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 7cccdb49af75 -r ffbc98d735bd linux-2.6-xen-sparse/drivers/xen/netback/netback.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Fri Sep 16 18:06:42 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Fri Sep 16 18:07:50 2005 @@ -57,8 +57,8 @@ #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 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 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); - - 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; - - /* - * 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; - } + netif_t *netif = netdev_priv(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; + + /* + * 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); -#endif -#endif - netif->rx_req_cons++; - netif_get(netif); - - skb_queue_tail(&rx_queue, skb); - tasklet_schedule(&net_rx_tasklet); - - return 0; + 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); + + skb_queue_tail(&rx_queue, skb); + tasklet_schedule(&net_rx_tasklet); + + 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 @@ */ 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; -#ifdef CONFIG_XEN_NETDEV_GRANT - gnttab_transfer_t *gop; -#else - 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; - - skb_queue_head_init(&rxq); - - mcl = rx_mcl; - mmu = rx_mmu; -#ifdef CONFIG_XEN_NETDEV_GRANT - gop = grant_rx_op; -#else - 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); - - /* 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++; - -#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++; -#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++; - - 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++; - - __skb_queue_tail(&rxq, skb); + 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; +#else + 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; + + skb_queue_head_init(&rxq); + + mcl = rx_mcl; + mmu = rx_mmu; +#ifdef CONFIG_XEN_NETDEV_GRANT + gop = grant_rx_op; +#else + 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); + + /* 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++; + +#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++; +#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++; + + mmuext->cmd = MMUEXT_REASSIGN_PAGE; + mmuext->arg1.mfn = old_mfn; + mmuext++; +#endif + mmu->ptr = ((maddr_t)new_mfn << PAGE_SHIFT) | + MMU_MACHPHYS_UPDATE; + mmu->val = __pa(vdata) >> PAGE_SHIFT; + mmu++; + + __skb_queue_tail(&rxq, skb); #ifdef DEBUG_GRANT - dump_packet('a', old_mfn, vdata); -#endif - /* Filled the batch queue? */ - if ( (mcl - rx_mcl) == ARRAY_SIZE(rx_mcl) ) - break; - } - - 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++; - -#ifdef CONFIG_XEN_NETDEV_GRANT - mcl[-2].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL; -#else - mcl[-3].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL; -#endif - if ( unlikely(HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl) != 0) ) - BUG(); - - 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; -#else - mmuext = rx_mmuext; -#endif - 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; -#ifdef CONFIG_XEN_NETDEV_GRANT - old_mfn = 0; /* XXX Fix this so we can free_mfn() on error! */ -#else - 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; - - netif->stats.tx_bytes += size; - netif->stats.tx_packets++; - - /* The update_va_mapping() must not fail. */ - BUG_ON(mcl[0].result != 0); - - /* 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; - } -#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; - } -#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; - } - - netif_put(netif); - dev_kfree_skb(skb); -#ifdef CONFIG_XEN_NETDEV_GRANT - mcl++; - gop++; -#else - mcl += 2; - mmuext += 1; -#endif - } - - 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); + dump_packet('a', old_mfn, vdata); +#endif + /* Filled the batch queue? */ + if ((mcl - rx_mcl) == ARRAY_SIZE(rx_mcl)) + break; + } + + 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++; + +#ifdef CONFIG_XEN_NETDEV_GRANT + mcl[-2].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL; +#else + mcl[-3].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL; +#endif + BUG_ON(HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl) != 0); + + 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; +#else + mmuext = rx_mmuext; +#endif + 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; +#ifdef CONFIG_XEN_NETDEV_GRANT + old_mfn = 0; /* XXX Fix this so we can free_mfn() on error! */ +#else + 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; + + netif->stats.tx_bytes += size; + netif->stats.tx_packets++; + + /* The update_va_mapping() must not fail. */ + BUG_ON(mcl[0].result != 0); + + /* 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; + } +#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; + } +#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; + } + + netif_put(netif); + dev_kfree_skb(skb); +#ifdef CONFIG_XEN_NETDEV_GRANT + mcl++; + gop++; +#else + mcl += 2; + mmuext += 1; +#endif + } + + while (notify_nr != 0) { + evtchn = notify_list[--notify_nr]; + rx_notify[evtchn] = 0; + notify_via_evtchn(evtchn); + } + + /* More work to do? */ + if (!skb_queue_empty(&rx_queue) && !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; - - 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); + 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); } 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; -#else - multicall_entry_t *mcl; -#endif - u16 pending_idx; - PEND_RING_IDX dc, dp; - netif_t *netif; - - 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)); -#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[-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL; - if ( unlikely(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0) ) - BUG(); - - mcl = tx_mcl; -#endif - while ( dealloc_cons != dp ) - { + gnttab_unmap_grant_ref_t *gop; +#else + multicall_entry_t *mcl; +#endif + u16 pending_idx; + PEND_RING_IDX dc, dp; + netif_t *netif; + + 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)); +#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[-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL; + BUG_ON(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0); + + mcl = tx_mcl; +#endif + while (dealloc_cons != dp) { #ifndef CONFIG_XEN_NETDEV_GRANT - /* The update_va_mapping() must not fail. */ - BUG_ON(mcl[0].result != 0); -#endif - - pending_idx = dealloc_ring[MASK_PEND_IDX(dealloc_cons++)]; - - netif = pending_tx_info[pending_idx].netif; - - make_tx_response(netif, pending_tx_info[pending_idx].req.id, - NETIF_RSP_OKAY); + /* The update_va_mapping() must not fail. */ + BUG_ON(mcl[0].result != 0); +#endif + + pending_idx = dealloc_ring[MASK_PEND_IDX(dealloc_cons++)]; + + netif = pending_tx_info[pending_idx].netif; + + make_tx_response(netif, pending_tx_info[pending_idx].req.id, + NETIF_RSP_OKAY); - 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); + 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); - netif_put(netif); + netif_put(netif); #ifndef CONFIG_XEN_NETDEV_GRANT - mcl++; -#endif - } - + 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; -#ifdef CONFIG_XEN_NETDEV_GRANT - gnttab_map_grant_ref_t *mop; -#else - multicall_entry_t *mcl; -#endif - unsigned int data_len; - - if ( dealloc_cons != dealloc_prod ) - net_tx_action_dealloc(); - -#ifdef CONFIG_XEN_NETDEV_GRANT - mop = tx_map_ops; -#else - 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); - - /* 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); - - /* Timer could already be pending in some 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; - } - - /* 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; - - /* - * 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); - - 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; - } - - pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)]; - - 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; - } - - /* 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++; -#else - MULTI_update_va_mapping_otherdomain( - mcl, MMAP_VADDR(pending_idx), - pfn_pte_ma(txreq.addr >> PAGE_SHIFT, PAGE_KERNEL), - 0, netif->domid); - - mcl++; -#endif - - memcpy(&pending_tx_info[pending_idx].req, &txreq, sizeof(txreq)); - pending_tx_info[pending_idx].netif = netif; - *((u16 *)skb->data) = pending_idx; - - __skb_queue_tail(&tx_queue, skb); - - pending_cons++; - -#ifdef CONFIG_XEN_NETDEV_GRANT - 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; -#endif - } - -#ifdef CONFIG_XEN_NETDEV_GRANT - if ( mop == tx_map_ops ) - return; - - BUG_ON(HYPERVISOR_grant_table_op( - GNTTABOP_map_grant_ref, tx_map_ops, mop - tx_map_ops)); - - mop = tx_map_ops; -#else - if ( mcl == tx_mcl ) - return; - - BUG_ON(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0); - - 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)); - - /* 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; -#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; - } - - 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; - - __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->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; - - netif->stats.rx_bytes += txreq.size; - netif->stats.rx_packets++; - - netif_rx(skb); - netif->dev->last_rx = jiffies; - -#ifdef CONFIG_XEN_NETDEV_GRANT - mop++; -#else - mcl++; -#endif - } + 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; +#else + multicall_entry_t *mcl; +#endif + unsigned int data_len; + + if (dealloc_cons != dealloc_prod) + net_tx_action_dealloc(); + +#ifdef CONFIG_XEN_NETDEV_GRANT + mop = tx_map_ops; +#else + 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); + + /* 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); + + /* Timer could already be pending in rare cases. */ + if (timer_pending(&netif->credit_timeout)) + break; + + /* 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? 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(); + + 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; + } + + /* 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)]; + + data_len = (txreq.size > PKT_PROT_LEN) ? + PKT_PROT_LEN : txreq.size; + + 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); +#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++; +#else + MULTI_update_va_mapping_otherdomain( + mcl, MMAP_VADDR(pending_idx), + pfn_pte_ma(txreq.addr >> PAGE_SHIFT, PAGE_KERNEL), + 0, netif->domid); + + mcl++; +#endif + + memcpy(&pending_tx_info[pending_idx].req, + &txreq, sizeof(txreq)); + pending_tx_info[pending_idx].netif = netif; + *((u16 *)skb->data) = pending_idx; + + __skb_queue_tail(&tx_queue, skb); + + pending_cons++; + +#ifdef CONFIG_XEN_NETDEV_GRANT + 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; +#endif + } + +#ifdef CONFIG_XEN_NETDEV_GRANT + if (mop == tx_map_ops) + return; + + BUG_ON(HYPERVISOR_grant_table_op( + GNTTABOP_map_grant_ref, tx_map_ops, mop - tx_map_ops)); + + mop = tx_map_ops; +#else + if (mcl == tx_mcl) + return; + + BUG_ON(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0); + + 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)); + + /* 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; +#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; + } + + 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; + + __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->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; + + netif->stats.rx_bytes += txreq.size; + netif->stats.rx_packets++; + + netif_rx(skb); + netif->dev->last_rx = jiffies; + +#ifdef CONFIG_XEN_NETDEV_GRANT + mop++; +#else + mcl++; +#endif + } } static void netif_idx_release(u16 pending_idx) { - 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); - - tasklet_schedule(&net_tx_tasklet); + 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); + + tasklet_schedule(&net_tx_tasklet); } static void netif_page_release(struct page *page) { - u16 pending_idx = page - virt_to_page(mmap_vstart); - - /* Ready for next use. */ - set_page_count(page, 1); - - netif_idx_release(pending_idx); + u16 pending_idx = page - virt_to_page(mmap_vstart); + + /* Ready for next use. */ + set_page_count(page, 1); + + 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; - - 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); + NETIF_RING_IDX i = netif->tx_resp_prod; + netif_tx_response_t *resp; + + resp = &netif->tx->ring[MASK_NETIF_TX_IDX(i)].resp; + resp->id = id; + resp->status = st; + wmb(); + netif->tx->resp_prod = netif->tx_resp_prod = ++i; + + mb(); /* Update producer before checking event threshold. */ + if (i == netif->tx->event) + notify_via_evtchn(netif->evtchn); } static int make_rx_response(netif_t *netif, @@ -882,110 +878,120 @@ u16 size, u16 csum_valid) { - 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; - - mb(); /* Update producer before checking event threshold. */ - return (i == netif->rx->event); + 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; + + 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; - - printk(KERN_ALERT "netif_schedule_list:\n"); - spin_lock_irq(&net_schedule_list_lock); - - list_for_each ( ent, &net_schedule_list ) - { - netif = list_entry(ent, netif_t, list); - printk(KERN_ALERT " %d: private(rx_req_cons=%08x rx_resp_prod=%08x\n", - i, netif->rx_req_cons, netif->rx_resp_prod); - printk(KERN_ALERT " tx_req_cons=%08x tx_resp_prod=%08x)\n", - netif->tx_req_cons, netif->tx_resp_prod); - printk(KERN_ALERT " shared(rx_req_prod=%08x rx_resp_prod=%08x\n", - netif->rx->req_prod, netif->rx->resp_prod); - printk(KERN_ALERT " rx_event=%08x tx_req_prod=%08x\n", - netif->rx->event, netif->tx->req_prod); - printk(KERN_ALERT " tx_resp_prod=%08x, tx_event=%08x)\n", - netif->tx->resp_prod, netif->tx->event); - i++; - } - - spin_unlock_irq(&net_schedule_list_lock); - printk(KERN_ALERT " ** End of netif_schedule_list **\n"); - - return IRQ_HANDLED; + struct list_head *ent; + netif_t *netif; + int i = 0; + + printk(KERN_ALERT "netif_schedule_list:\n"); + spin_lock_irq(&net_schedule_list_lock); + + list_for_each (ent, &net_schedule_list) { + netif = list_entry(ent, netif_t, list); + printk(KERN_ALERT " %d: private(rx_req_cons=%08x " + "rx_resp_prod=%08x\n", + i, netif->rx_req_cons, netif->rx_resp_prod); + printk(KERN_ALERT " tx_req_cons=%08x tx_resp_prod=%08x)\n", + netif->tx_req_cons, netif->tx_resp_prod); + printk(KERN_ALERT " shared(rx_req_prod=%08x " + "rx_resp_prod=%08x\n", + netif->rx->req_prod, netif->rx->resp_prod); + printk(KERN_ALERT " rx_event=%08x tx_req_prod=%08x\n", + netif->rx->event, netif->tx->req_prod); + printk(KERN_ALERT " tx_resp_prod=%08x, tx_event=%08x)\n", + netif->tx->resp_prod, netif->tx->event); + i++; + } + + spin_unlock_irq(&net_schedule_list_lock); + printk(KERN_ALERT " ** End of netif_schedule_list **\n"); + + return IRQ_HANDLED; } static int __init netback_init(void) { - int i; - struct page *page; - - if ( !(xen_start_info->flags & SIF_NET_BE_DOMAIN) && - !(xen_start_info->flags & SIF_INITDOMAIN) ) - return 0; - - IPRINTK("Initialising Xen netif backend.\n"); -#ifdef CONFIG_XEN_NETDEV_GRANT - 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); - - 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; + int i; + struct page *page; + + if (!(xen_start_info->flags & SIF_NET_BE_DOMAIN) && + !(xen_start_info->flags & SIF_INITDOMAIN)) + return 0; + + IPRINTK("Initialising Xen netif backend.\n"); +#ifdef CONFIG_XEN_NETDEV_GRANT + 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); + + 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; - 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); - } - - pending_cons = 0; - pending_prod = MAX_PENDING_REQS; - for ( i = 0; i < MAX_PENDING_REQS; i++ ) - pending_ring[i] = i; - - spin_lock_init(&net_schedule_list_lock); - INIT_LIST_HEAD(&net_schedule_list); - - netif_xenbus_init(); - - (void)request_irq(bind_virq_to_irq(VIRQ_DEBUG), - netif_be_dbg, SA_SHIRQ, - "net-be-dbg", &netif_be_dbg); - - return 0; + 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); + } + + pending_cons = 0; + pending_prod = MAX_PENDING_REQS; + for (i = 0; i < MAX_PENDING_REQS; i++) + pending_ring[i] = i; + + spin_lock_init(&net_schedule_list_lock); + INIT_LIST_HEAD(&net_schedule_list); + + netif_xenbus_init(); + + (void)request_irq(bind_virq_to_irq(VIRQ_DEBUG), + netif_be_dbg, SA_SHIRQ, + "net-be-dbg", &netif_be_dbg); + + return 0; } static void 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 -r 7cccdb49af75 -r ffbc98d735bd linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Fri Sep 16 18:06:42 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Fri Sep 16 18:07:50 2005 @@ -294,3 +294,13 @@ { 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: + */ diff -r 7cccdb49af75 -r ffbc98d735bd linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Fri Sep 16 18:06:42 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Fri Sep 16 18:07:50 2005 @@ -54,43 +54,10 @@ #include <asm-xen/balloon.h> #include <asm/page.h> #include <asm/uaccess.h> - -#ifdef CONFIG_XEN_NETDEV_GRANT #include <asm-xen/xen-public/grant_table.h> #include <asm-xen/gnttab.h> -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 -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 @@ -124,7 +91,6 @@ #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); @@ -147,45 +113,50 @@ #define netfront_info net_private struct net_private { - 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 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; - netif_tx_interface_t *tx; - netif_rx_interface_t *rx; - - spinlock_t tx_lock; - spinlock_t rx_lock; - - unsigned int handle; - unsigned int evtchn; - - /* What is the status of our connection to the remote backend? */ + netif_tx_interface_t *tx; + netif_rx_interface_t *rx; + + spinlock_t tx_lock; + spinlock_t rx_lock; + + unsigned int handle; + unsigned int evtchn; + + /* 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; - - /* Is this interface open or closed (down or up)? */ + unsigned int backend_state; + + /* Is this interface open or closed (down or up)? */ #define UST_CLOSED 0 #define UST_OPEN 1 - unsigned int user_state; - - /* Receive-ring batched refills. */ + unsigned int user_state; + + /* 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; - - /* - * {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]; + 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]; + + 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; @@ -197,32 +168,32 @@ }; /* 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. @@ -232,625 +203,627 @@ */ static int send_fake_arp(struct net_device *dev) { - struct sk_buff *skb; - u32 src_ip, dst_ip; - - 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; - - 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); + struct sk_buff *skb; + u32 src_ip, dst_ip; + + 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; + + 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); } static int network_open(struct net_device *dev) { - struct net_private *np = netdev_priv(dev); - - memset(&np->stats, 0, sizeof(np->stats)); - - np->user_state = UST_OPEN; - - network_alloc_rx_buffers(dev); - np->rx->event = np->rx_resp_cons + 1; - - netif_start_queue(dev); - - return 0; + struct net_private *np = netdev_priv(dev); + + memset(&np->stats, 0, sizeof(np->stats)); + + np->user_state = UST_OPEN; + + network_alloc_rx_buffers(dev); + np->rx->event = np->rx_resp_cons + 1; + + netif_start_queue(dev); + + 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; - - if (np->backend_state != BEST_CONNECTED) - return; - - 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]; -#ifdef CONFIG_XEN_NETDEV_GRANT - if (unlikely(gnttab_query_foreign_access(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; -#endif - ADD_ID_TO_FREELIST(np->tx_skbs, id); - dev_kfree_skb_irq(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; + + 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]; +#ifdef CONFIG_XEN_NETDEV_GRANT + 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); + } - 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); - -#ifdef CONFIG_XEN_NETDEV_GRANT - 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); - } + /* + * 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: +#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); + } } 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; -#ifdef CONFIG_XEN_NETDEV_GRANT - grant_ref_t ref; -#endif - - 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); - } - - /* 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; - - skb->dev = dev; - - id = GET_ID_FROM_FREELIST(np->rx_skbs); - - np->rx_skbs[id] = skb; + 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; +#endif + + 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++) { + 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; + + for (i = 0; ; i++) { + if ((skb = __skb_dequeue(&np->rx_batch)) == NULL) + break; + + skb->dev = dev; + + id = GET_ID_FROM_FREELIST(np->rx_skbs); + + np->rx_skbs[id] = skb; - 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); - if (unlikely((signed short)ref < 0)) { - printk(KERN_ALERT "#### netfront can't claim rx reference\n"); - BUG(); - } - 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); - - /* Remove this page from pseudo phys 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); - } - - /* 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; - - 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); - - /* 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"); - - /* 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; + 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); + 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); + + /* 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); + } + + /* 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; + + 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); + + /* 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"); + + /* Above is a suitable barrier to ensure backend will see requests. */ + np->rx->req_prod = req_prod + i; + + /* 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; -#ifdef CONFIG_XEN_NETDEV_GRANT - 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((((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; - } + 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; +#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((((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); - - if (np->backend_state != BEST_CONNECTED) { - spin_unlock_irq(&np->tx_lock); - goto drop; - } - - i = np->tx->req_prod; - - id = GET_ID_FROM_FREELIST(np->tx_skbs); - np->tx_skbs[id] = skb; - - tx = &np->tx->ring[MASK_NETIF_TX_IDX(i)].req; - - tx->id = id; -#ifdef CONFIG_XEN_NETDEV_GRANT - ref = gnttab_claim_grant_reference(&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; - grant_tx_ref[id] = ref; + spin_lock_irq(&np->tx_lock); + + if (np->backend_state != BEST_CONNECTED) { + spin_unlock_irq(&np->tx_lock); + goto drop; + } + + i = np->tx->req_prod; + + id = GET_ID_FROM_FREELIST(np->tx_skbs); + np->tx_skbs[id] = skb; + + tx = &np->tx->ring[MASK_NETIF_TX_IDX(i)].req; + + tx->id = id; +#ifdef CONFIG_XEN_NETDEV_GRANT + 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; -#endif - 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; - - network_tx_buf_gc(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); - - 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); - - return 0; + 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); + + wmb(); /* Ensure that backend will see the request. */ + np->tx->req_prod = i + 1; + + network_tx_buf_gc(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); + + 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); + + 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; - - 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); - - return IRQ_HANDLED; + 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); + + if ((np->rx_resp_cons != np->rx->resp_prod) && + (np->user_state == UST_OPEN)) + netif_rx_schedule(dev); + + 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; -#ifdef CONFIG_XEN_NETDEV_GRANT - unsigned long mfn; - grant_ref_t ref; -#endif - - spin_lock(&np->rx_lock); - - if (np->backend_state != BEST_CONNECTED) { - spin_unlock(&np->rx_lock); - return 0; - } - - 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'. */ - - 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; - } - -#ifdef CONFIG_XEN_NETDEV_GRANT - ref = 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; - } - - grant_rx_ref[rx->id] = GRANT_INVALID_REF; - mfn = gnttab_end_foreign_transfer_ref(ref); - gnttab_release_grant_reference(&gref_rx_head, ref); -#endif - - skb = np->rx_skbs[rx->id]; - ADD_ID_TO_FREELIST(np->rx_skbs, rx->id); - - /* NB. We handle skb overflow later. */ -#ifdef CONFIG_XEN_NETDEV_GRANT - skb->data = skb->head + rx->addr; + 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; +#endif + + spin_lock(&np->rx_lock); + + if (np->backend_state != BEST_CONNECTED) { + spin_unlock(&np->rx_lock); + return 0; + } + + 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'. */ + + 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]; + + 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); +#endif + + skb = np->rx_skbs[rx->id]; + ADD_ID_TO_FREELIST(np->rx_skbs, rx->id); + + /* NB. We handle skb overflow later. */ +#ifdef CONFIG_XEN_NETDEV_GRANT + skb->data = skb->head + rx->addr; #else - skb->data = skb->head + (rx->addr & ~PAGE_MASK); -#endif - skb->len = rx->status; - skb->tail = skb->data + skb->len; - - if ( rx->csum_valid ) - skb->ip_summed = CHECKSUM_UNNECESSARY; - - np->stats.rx_packets++; - np->stats.rx_bytes += rx->status; - - /* Remap the page. */ -#ifdef CONFIG_XEN_NETDEV_GRANT - mmu->ptr = ((unsigned long long)mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE; + skb->data = skb->head + (rx->addr & ~PAGE_MASK); +#endif + skb->len = rx->status; + skb->tail = skb->data + skb->len; + + if ( rx->csum_valid ) + skb->ip_summed = CHECKSUM_UNNECESSARY; + + np->stats.rx_packets++; + np->stats.rx_bytes += rx->status; + + /* Remap the page. */ +#ifdef CONFIG_XEN_NETDEV_GRANT + mmu->ptr = ((maddr_t)mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE; #else - mmu->ptr = (rx->addr & PAGE_MASK) | MMU_MACHPHYS_UPDATE; -#endif - 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); + mmu->ptr = (rx->addr & PAGE_MASK) | MMU_MACHPHYS_UPDATE; +#endif + 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); #else - MULTI_update_va_mapping(mcl, (unsigned long)skb->head, - pfn_pte_ma(rx->addr >> PAGE_SHIFT, - PAGE_KERNEL), 0); -#endif - 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); + MULTI_update_va_mapping(mcl, (unsigned long)skb->head, + pfn_pte_ma(rx->addr >> PAGE_SHIFT, + PAGE_KERNEL), 0); +#endif + mcl++; + +#ifdef CONFIG_XEN_NETDEV_GRANT + 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); - } - - - /* Some pages are no longer absent... */ - balloon_update_driver_allowance(-work_done); - - /* 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) { -#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 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); - - 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; - } + __skb_queue_tail(&rxq, skb); + } + + /* 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); + } + + 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; + + /* 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); + + /* 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; + } - /* 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); - - /* Pass it up. */ - netif_receive_skb(skb); - dev->last_rx = jiffies; - } - - 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; - - network_alloc_rx_buffers(dev); - - *pbudget -= work_done; - dev->quota -= work_done; - - if (work_done < budget) { - local_irq_save(flags); - - np->rx->event = i + 1; + /* 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; + } + + 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; + + network_alloc_rx_buffers(dev); + + *pbudget -= work_done; + dev->quota -= work_done; + + if (work_done < budget) { + local_irq_save(flags); + + 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; - } - - local_irq_restore(flags); - } - - spin_unlock(&np->rx_lock); - - return more_to_do; + /* 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); + } + + spin_unlock(&np->rx_lock); + + 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; - - np = netdev_priv(dev); - spin_lock_irq(&np->tx_lock); - spin_lock(&np->rx_lock); - - /* 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 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]; - - tx = &np->tx->ring[requeue_idx++].req; - - tx->id = i; -#ifdef CONFIG_XEN_NETDEV_GRANT - gnttab_grant_foreign_access_ref(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; + 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); + + /* 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 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]; + + tx = &np->tx->ring[requeue_idx++].req; + + 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; #else - tx->addr = virt_to_mfn(skb->data) << PAGE_SHIFT; -#endif - 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; - - /* 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) { + tx->addr = virt_to_mfn(skb->data) << PAGE_SHIFT; +#endif + 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; + + /* 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(grant_rx_ref[i], np->backend_id); - np->rx->ring[requeue_idx].req.gref = grant_rx_ref[i]; -#endif - np->rx->ring[requeue_idx].req.id = i; - 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); - - if (np->user_state == UST_OPEN) - netif_start_queue(dev); - - spin_unlock(&np->rx_lock); - spin_unlock_irq(&np->tx_lock); + 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++; + } + } + + 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); + + if (np->user_state == UST_OPEN) + netif_start_queue(dev); + + spin_unlock(&np->rx_lock); + spin_unlock_irq(&np->tx_lock); } static void show_device(struct net_private *np) @@ -887,6 +860,15 @@ 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, @@ -901,84 +883,107 @@ 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; - - 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; + 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; + } + + 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); - - 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); -#ifdef CONFIG_XEN_NETDEV_GRANT - 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; -#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->weight = 64; - netdev->features = NETIF_F_IP_CSUM; - - SET_ETHTOOL_OPS(netdev, &network_ethtool_ops); - - if ((err = register_netdev(netdev)) != 0) { - printk(KERN_WARNING "%s> register_netdev err=%d\n", __FUNCTION__, err); - goto exit; - } - - if ((err = xennet_proc_addif(netdev)) != 0) { - unregister_netdev(netdev); - goto exit; - } - - np->netdev = netdev; - - exit: - if ((err != 0) && (netdev != NULL)) - kfree(netdev); - else if (val != NULL) - *val = netdev; - return err; + 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; + + /* 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; +#endif + } + + 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; +#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; + + 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 = xennet_proc_addif(netdev)) != 0) { + unregister_netdev(netdev); + goto exit_free_grefs; + } + + np->netdev = netdev; + + 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); +#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; } @@ -989,20 +994,20 @@ 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; - - /* UP event and is it one of our devices? */ - if (event == NETDEV_UP && dev->open == network_open) - (void)send_fake_arp(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); - 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[] = { @@ -1341,72 +1346,50 @@ static int wait_for_netif(void) { - 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); - } - - if (netif_state != NETIF_STATE_CONNECTED) { - WPRINTK("Timeout connecting to device!\n"); - err = -ENOSYS; - } - return err; + 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); + } + + 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; - - if (xen_start_info->flags & SIF_INITDOMAIN) - return 0; - - if ((err = xennet_proc_init()) != 0) - return err; - - 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(); - - wait_for_netif(); - - return err; + int err = 0; + + if (xen_start_info->flags & SIF_INITDOMAIN) + return 0; + + if ((err = xennet_proc_init()) != 0) + return err; + + IPRINTK("Initialising virtual ethernet driver.\n"); + + (void)register_inetaddr_notifier(¬ifier_inetdev); + + init_net_xenbus(); + + wait_for_netif(); + + return err; } 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 @@ -1416,147 +1399,159 @@ #define TARGET_CUR 2UL static int xennet_proc_read( - 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; + 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; - 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; + 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; } static int xennet_proc_write( - 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; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - 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'; - - 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); - - 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); - - spin_unlock(&np->rx_lock); - - return count; + 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; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + 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'; + + 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); + + 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); + + spin_unlock(&np->rx_lock); + + 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]; - - sprintf(name, "xen/net/%s", dev->name); - - 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->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); - - cur->read_proc = xennet_proc_read; - cur->write_proc = xennet_proc_write; - cur->data = (void *)((unsigned long)dev | TARGET_CUR); - - return 0; + struct proc_dir_entry *dir, *min, *max, *cur; + char name[30]; + + sprintf(name, "xen/net/%s", dev->name); + + 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->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); + + cur->read_proc = xennet_proc_read; + cur->write_proc = xennet_proc_write; + cur->data = (void *)((unsigned long)dev | TARGET_CUR); + + 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]; - - 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_cur", dev->name); - remove_proc_entry(name, NULL); - - sprintf(name, "xen/net/%s", dev->name); - remove_proc_entry(name, NULL); + char name[30]; + + 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_cur", 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: + */ diff -r 7cccdb49af75 -r ffbc98d735bd linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Fri Sep 16 18:06:42 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Fri Sep 16 18:07:50 2005 @@ -130,12 +130,12 @@ if ( (msg[j].va + (msg[j].npages<<PAGE_SHIFT)) > 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<<PAGE_SHIFT, - vma->vm_page_prot, - mmapcmd.dom)) < 0 ) + if ( (rc = direct_remap_pfn_range(vma, + msg[j].va&PAGE_MASK, + msg[j].mfn, + msg[j].npages<<PAGE_SHIFT, + vma->vm_page_prot, + mmapcmd.dom)) < 0 ) return rc; } } diff -r 7cccdb49af75 -r ffbc98d735bd linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h Fri Sep 16 18:06:42 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h Fri Sep 16 18:07:50 2005 @@ -460,7 +460,7 @@ #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 @@ 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 -r 7cccdb49af75 -r ffbc98d735bd linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h Fri Sep 16 18:06:42 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h Fri Sep 16 18:07:50 2005 @@ -526,7 +526,7 @@ #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 @@ 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 _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |